How to get the Base64 content of multiple uploaded images in Google Apps Script?

Viewed 242

I'm creating a sidebar form within Google Sheets using Google Apps Script where users can upload at least one image. After that, I want to get the Base64 encoded content of each image and the image's file name. Then, I will make a request to SendGrid's API to create and send an email with attachments being the images that the user has uploaded.

Here is the code I have so far:

Form.html

<form onsubmit="handleFormSubmit(this)">
    <div class="custom-file">
        <input type="file" class="custom-file-input" id="images_input" name="images_input" multiple required>
        <label class="custom-file-label" for="images_input">Select images...</label>
    </div> 
    <button type="submit">Submit</button>
</form>

<script>
function handleFormSubmit(formObject) {
    google.script.run.processForm(formObject);
}
</script>

Code.gs

function processForm(formObject) {
    var images = formObject.images_input;
    var base64Images = Utilities.base64Encode(images);

    // Set up the request to SendGrid
    var API_KEY = PropertiesService.getScriptProperties().getProperty('API_KEY');
    var sendGridUrl = 'https://api.sendgrid.com/v3/mail/send';

    var headers = {
        'Authorization': 'Bearer ' + API_KEY
    };

    var data = {
        "personalizations": [{
            "to": [{
                "email": ...
            }],
            "dynamic_template_data": {
                ...
            }
        }],
        "attachments": [{
            "content": base64Images,
            "filename": "somefilename"
        }],
        "from": {
            "email": ...
        },
        "template_id": ...",
    };

    var options = {
        'method': 'post',
        'contentType': 'application/json',
        'headers': headers,
        'payload': JSON.stringify(data)
    };

    UrlFetchApp.fetch(sendGridUrl, options);
}

It's not working (obviously). I'm stuck at the part where I need to get the Base64 encoded content of each image: I don't think I'm doing that correctly. Should I use FileReader on the client-side, or Utilities.base64Encode on the server-side do get what I want? Any ideas are appreciated!

1 Answers

I believe your goal as follows.

  • You want to retrieve the file and send it to Google Apps Script as base64 data.

I think that in this case, you can retrieve the file using FileReader as you have already mentioned. When FileReader is used, the base64 data can be directly retrieved at Javascript side. So when your script is modified, it becomes as follows.

Modified script:

HTML&Javascript side:

From:
function handleFormSubmit(formObject) {
    google.script.run.processForm(formObject);
}
To:
function handleFormSubmit(formObject) {
  Promise.all([...formObject.images_input.files].map((file, i) => {
    const fr = new FileReader();
    return new Promise((r) => {
      fr.onload = (f) => r({filename: file.name, base64Data: f.target.result.split(",")[1]});
      fr.readAsDataURL(file);
    });
  }))
  .then((obj) => {
    google.script.run.processForm(obj);
  });
}

Google Apps Script side:

From:
function processForm(formObject) {
    var images = formObject.images_input;
    var base64Images = Utilities.base64Encode(images);
To:
function processForm(base64Images) {
  • In this case, base64Images is an array like [{base64Data: "###base64ImageData1###", filename: "filename1"},{base64Data: "###base64ImageData2###", filename: "filename2"},,,].

Note:

  • In this modification, it supposes that you have alredy been able to use the API you want to use. Please be careful this.

Reference:

Related