Katshun0307
Katshun0307

Reputation: 23

How do I convert jpg or png image to Blob via a Google Apps Script Web App?

I want to http post an image from html form to google apps script web app, and then add that image to google drive.

my apps script is below.

function doPost(e){
  var date = new Date();
  var timestamp = date.toString()
  var adress = e.parameter.adress;
  var cost = e.parameter.cost;
  var item = e.parameter.item;
  var check = e.parameter.image;

  //add file to drive
  var destination_id = "some ID"
  var destination = DriveApp.getFolderById(destination_id);
  destination.createFile(check);
};

when I execute, it returns a error ; cannot find method: createFile(String)

I think this is because "check" is a string, and I want to convert the submitted image to Blob.

How can I do this?

Upvotes: 1

Views: 6437

Answers (1)

Tanaike
Tanaike

Reputation: 201378

How about following sample? Added "getAs()". https://developers.google.com/apps-script/reference/drive/file#getAs(String)

These are very simple html and gas script I used for this test.

HTML: This file name is "form.html".

<form>
  <input type="file" name="imageFile">
  <input type="button" value="ok" onclick="google.script.run.upload(this.parentNode)">
</form>

GAS script:

function doGet() {
  return HtmlService.createHtmlOutputFromFile('form.html');
}

function upload(e) {
  var destination_id = "some ID";
  var img = e.imageFile;
  var contentType = "image/jpeg";
  var destination = DriveApp.getFolderById(destination_id);
  var img = img.getAs(contentType);
  destination.createFile(img);  
}

For this sample script, if you want to save as a jpeg file, please change 'contentType' from 'image/png' to 'image/jpeg'. When you upload png file for contentType of 'image/jpeg', the png file is converted to jpeg file by 'getAs()'.

Updated: March 19, 2020

When V8 is enabled, it seems that this.parentNode cannot be sent to Google Apps Script side. I'm not sure whether this is a bug or the specification. I think that this might be resolved in the future update. But as the current workaround, I would like to add one more sample script for uploading the file using Web Apps, dialog and sidebar.

In this case, the file is sent to Google Apps Script side as the byte array. And the file is created from the byte array at Google Apps Script side.

HTML & Javascript: index.html

<input id="file" type="file" onchange="saveFile(this)" />
<script>
  function saveFile(f) {
    const file = f.files[0];
    const fr = new FileReader();
    fr.onload = function(e) {
      const obj = {
        filename: file.name,
        mimeType: file.type,
        bytes: [...new Int8Array(e.target.result)]
      };
      google.script.run.withSuccessHandler(e => console.log(e)).saveFile(obj);
    };
    fr.readAsArrayBuffer(file);
  }
</script>

Google Apps Script: Code.gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile('index.html');
}

function saveFile(e) {
  var blob = Utilities.newBlob(e.bytes, e.mimeType, e.filename);
  DriveApp.createFile(blob);
  return "Done.";
}

Updated: December 9, 2021

After V8 runtime was released, there was a bug that when the file is sent from HTML form to Google Apps Script side using google.script.run, the file blob was the invalid data.

From Apps Script Pulse by Martin Hawksey, it was found that the invalid blob of sending the file of HTML form to Google Apps Script side using google.script.run has finally been resolved. In this case, this script can be used with V8 runtime.

HTML & Javascript side: index.html

<form>
  <input type="file" name="file" onchange="google.script.run.withSuccessHandler(console.log).upload(this.parentNode)">
</form>

Google Apps Script side: Code.gs

const doGet = _ => HtmlService.createHtmlOutputFromFile('index.html');
const upload = ({file}) => DriveApp.createFile(file).getId();

IMPORTANT:

As an important point, in the current stage, when the above HTML is accessed as Web Apps (doGet), this script works. But when the above HTML is accessed as a dialog and a sidebar, file at the Google Apps Script side is undefined. By this, it seems that in the current stage, this HTML can be used with only Web Apps. Please be careful about this. I would like to believe that this situation is resolved in the future update.

Upvotes: 5

Related Questions