1

Trying to upload a png file using S3-for-Google-Apps-Script library to S3 bucket:

// get the image blob
const imgBlob = UrlFetchApp.fetch('imageUrl').getBlob();

// init S3 instance
const s3 = S3.getInstance(awsAccessKeyId, awsSecretKey);

// upload the image to S3 bucket
s3.putObject(bucketName, 'test.png', imgBlob, { logRequests:true });

The file is uploading to S3 but not in a perfect way! It looks like this:

file image

If I download the image and open getting the error:

"It may be damaged or use a file format that Preview doesn’t recognize."

So, how can I upload a .png file to amazon S3 bucket?


I can correctly upload the image when 'base64' is used to s3.putObject():

const base64 = Utilities.base64Encode(imgBlob.getBytes());
s3.putObject(bucketName, 'test.png', base64, { logRequests:true });
// go to S3 and clicking on the link I can see the base64 string

But this is uploading as String e.g. when I go S3 & click on test.png I see something like this: "iVBORw0KGgoAAAANSUhEUgAAAgAAAAI ... II=", but I want to see the actual image, not a String.

Sajib Khan
  • 22,878
  • 9
  • 63
  • 73
  • You can correctly upload the image when the base64 is used to `s3.putObject()`. Is my understanding correct? – Tanaike Apr 29 '20 at 00:03
  • Yes, I can upload base64 in S3 correctly! – Sajib Khan Apr 29 '20 at 00:05
  • Thank you for replying. When I saw the script of "S3-for-Google-Apps-Script", it seems that the blob is sent with `getDataAsString()`. [Ref](https://github.com/eschultink/S3-for-Google-Apps-Script/blob/a18b2032ffe3716461716f97dd867c54ec7cb859/S3.gs#L142) I think this might be the reason of issue. By this, the base64 data can be correctly used while the blob cannot be directly used. At the API you want to use, can I ask you about the other available types except for the base64? – Tanaike Apr 29 '20 at 00:10
  • Ah.. ok, sure! Basically I need to fetch a public image `UrlFetchApp.fetch('imageUrl')` and upload it in S3 as a `png` image. – Sajib Khan Apr 29 '20 at 00:13

1 Answers1

3

I believe your situation and goal as follows.

  • In your situation, the base64 data of the image can be uploaded. But, the uploaded data is not the image. It's the string data.
  • In your goal, you want to upload the image file of the publicly shared image using the image URL.

For this, how about this answer?

Issue and workaround:

When I saw the script of "S3-for-Google-Apps-Script", it seems that the URL cannot be directly used for s3.putObject(). And, the inputted blob is converted to the string type using getDataAsString(). I think that this is the reason of your issue.

In this answer, I would like to propose to modify the GAS library of "S3-for-Google-Apps-Script" for using the byte array to payload.

Usage:

At first, please copy the GAS project of S3-for-Google-Apps-Script, and please modify this as follows.

Modified script:

About S3.prototype.putObject in the file of S3.gs, please modify as follows.

From:
request.setContent(object.getDataAsString());
To:
request.setContent(object.getBytes());

And, about S3Request.prototype.setContent in the file of S3Request.gs, please modify as follows.

From:
if (typeof content != 'string') throw 'content must be passed as a string'
To:
// if (typeof content != 'string') throw 'content must be passed as a string'

And, about S3Request.prototype.getContentMd5_ in the file of S3Request.gs, please modify as follows.

From:
return Utilities.base64Encode(Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, this.content, Utilities.Charset.UTF_8));
To:
return Utilities.base64Encode(Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, this.content));

Sample script:

And, for above modified script, please test the following script.

const imageUrl = "###";  // Please set the image URL.
const s3 = S3.getInstance(awsAccessKeyId, awsSecretKey);  // Please set them.

const imageBlob = UrlFetchApp.fetch(imageUrl).getBlob();
s3.putObject(bucketName, 'test.png', imageBlob, { logRequests:true });
  • By this, your token can be created by the modified library and use it.
  • When I checked this official document, I thought that the byte array might be able to be used.

References:

Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • It's uploading as a base64 String, e.g. when I go S3 & click on `test.png` I see like: `"iVBORw0KGgoAAAANSUhEUgAAAgAAAAI ... II="` but I want to see the actual image not string. FYI, this is the exact similar as my working version! – Sajib Khan Apr 29 '20 at 00:46
  • @Sajib Khan Thank you for replying. When I had asked `You can correctly upload the image when the base64 is used to s3.putObject().`, you said `Yes, I can upload base64 in S3 correctly!`. And also, I confirmed `In your situation, the base64 data of the image can be correctly uploaded as the image.` at my answer, how about this? – Tanaike Apr 29 '20 at 00:48
  • sorry, there have been misunderstanding! .. I guessed you asked if I've any issue when uploading base64 string to S3! .. updated OP – Sajib Khan Apr 29 '20 at 00:50
  • @Sajib Khan Thank you for replying. In your situation, the base64 data of the image can NOT be correctly uploaded as the image. Is my understanding correct? – Tanaike Apr 29 '20 at 00:59
  • "base64 data of the image can NOT be correctly uploaded as the image" - Yes, it's not uploading as a image(`.png` format) rather uploading as a String. – Sajib Khan Apr 29 '20 at 01:02
  • @Sajib Khan Thank you for replying. For example, when the byte array of the image is used to `payload`, what result will you get? – Tanaike Apr 29 '20 at 01:06
  • I get like: `[-119,80,78, ... ,66,96,-126]` – Sajib Khan Apr 29 '20 at 01:09
  • @Sajib Khan Thank you for replying. I apologize for my poor English skill. For directly using the byte array, I added one more sample script. Could you please confirm it? – Tanaike Apr 29 '20 at 01:12
  • @Sajib Khan I'm not sure whether the endpoint of `http://bucket.s3.amazonaws.com/googlehome` is correctly for your situation. I apologize for this. So please check it again. – Tanaike Apr 29 '20 at 01:27
  • yeah, I set the url correctly.. but `"Authorization": "AWS ###",` what is the value for '###' here!? – Sajib Khan Apr 29 '20 at 01:35
  • @Sajib Khan I have to apologize. I noticed the modification point of the script. So I updated it. Could you please confirim it? – Tanaike Apr 29 '20 at 01:35
  • @Sajib Khan That is your token for accessing to the API. – Tanaike Apr 29 '20 at 01:36
  • @Sajib Khan Thank you for replying. When I checked [this official document](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html), I thought that the byte array might be able to be used. But if this was not the direct solution of your issue, I have to apologize. – Tanaike Apr 29 '20 at 01:54
  • Error: "Exception: The parameters (Blob) don't match the method signature for Utilities.base64Encode." for this line `const base64 = Utilities.base64Encode(imageBlob);` – Sajib Khan Apr 29 '20 at 02:14
  • @Sajib Khan Thank you for replying. I apologize for the inconvenience. I noticed that the modification point of the sample script. I updated it. Could you please confirm it? In this case, the blob is directly used. – Tanaike Apr 29 '20 at 02:15