Search code examples
jquerygoogle-apps-scriptgoogle-chrome-extensionfile-uploadblob

How to POST images from chrome extension to Google Drive using Google Apps Script WebApp and JQuery


I have a Google Chrome extension that I require to generate an image/png type image when I press CTRL + V (This works OK). After that I require to send this image to Google Drive using a Google Apps Script web application. But I have not been able to figure out how to do this. I am using ajax with jQuery

This is the code I have used to capture and create the image and works fine

$(partial).on('paste', e => { // partial is an dynamic html
    e = e.originalEvent
    let item = Array.from(e.clipboardData.items).find(x => /^image\//.test(x.type))
    let blob = item.getAsFile()
    let base = URL.createObjectURL(blob)
    let img = new Image()
    img.src = base
    img.onload = function () {
        let w = this.width
        let h = this.height
        $(partial).find('.img-evi').attr('width', w)
        $(partial).find('.img-evi').attr('height', h)
        $(partial).find('.img-evi').attr('src', base) // show the image paste in screen

        let reader = new FileReader() // try to send the image to Google Drive
        reader.onload = function (e) {
            const file = new File([blob], "capture.png", {
                type: 'image/png'
            })
            var fd = new FormData()
            fd.append("image", file)
            $.ajax({ // Call Google Apps Script WebApp by POST
                type: "POST",
                enctype: 'multipart/form-data',
                url: "https://script.google.com/macros/s/#########/exec",
                data: fd,
                processData: false,
                contentType: false,
                cache: false,
                success: (data) => {
                    alert("yes");
                },
                error: function (xhr, status, error) {
                    alert(xhr.responseText);
                }
            });
        }
        reader.readAsDataURL(blob);
    }
    img.remove()
})

In apps script i have that

function doPost(e) {
  let FOLDER = DriveApp.getFolderById('### Folder ID ######')
  let imgBlob = Utilities.newBlob(e.postData, 'image/png', "### how to get name ? ###")
  let fileId = FOLDER.createFile(imgBlob).getId()
  return ContentService.createTextOutput(JSON.stringify({
    ok: true,
    data: { id: fileId },
    title: 'Success',
    message: `The image id is ${fileId}.`
  })).setMimeType(ContentService.MimeType.JSON)
}

Thanks for your help


Solution

  • Modification points:

    • In your script, file is Blob. I think that this cannot be directly used for sending to Web Apps.
    • In this modification, the data is converted to the int8array and is sent it to Web Apps as the string value.
    • By this, it is required to modify your Google Apps Script side.

    When these points are reflected to your script, it becomes as follows.

    Javascript side:

    From:

    let reader = new FileReader() // try to send the image to Google Drive
    reader.onload = function (e) {
        const file = new File([blob], "capture.png", {
            type: 'image/png'
        })
        var fd = new FormData()
        fd.append("image", file)
        $.ajax({ // Call Google Apps Script WebApp by POST
            type: "POST",
            enctype: 'multipart/form-data',
            url: "https://script.google.com/macros/s/#########/exec",
            data: fd,
            processData: false,
            contentType: false,
            cache: false,
            success: (data) => {
                alert("yes");
            },
            error: function (xhr, status, error) {
                alert(xhr.responseText);
            }
        });
    }
    reader.readAsDataURL(blob);
    

    To:

    let reader = new FileReader();
    reader.onload = function (e) {
      const values = { data: [...new Int8Array(e.target.result)], filename: "capture.png", mimeType: "image/png" };
      $.ajax({
        url: "https://script.google.com/macros/s/###/exec",
        method: "POST",
        dataType: "json",
        data: JSON.stringify(values),
        processData: false,
        contentType: false,
        cache: false,
        success: (data) => {
          console.log(data)
          alert("yes");
        },
        error: function (xhr, status, error) {
          alert(xhr.responseText);
        }
      });
    }
    reader.readAsArrayBuffer(blob);
    

    Google Apps Script side:

    function doPost(e) {
      const { data, filename, mimeType } = JSON.parse(e.postData.contents);
      let FOLDER = DriveApp.getFolderById('### Folder ID ######');
      let imgBlob = Utilities.newBlob(data, mimeType, filename);
      let fileId = FOLDER.createFile(imgBlob).getId();
      return ContentService.createTextOutput(JSON.stringify({
        ok: true,
        data: { id: fileId },
        title: 'Success',
        message: `The image id is ${fileId}.`
      })).setMimeType(ContentService.MimeType.JSON)
    }
    

    Note:

    References: