Skip to content

Instantly share code, notes, and snippets.

@tanaikech
Created September 4, 2020 06:30
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save tanaikech/58d96c023468fc1922d67764251b25e0 to your computer and use it in GitHub Desktop.
Save tanaikech/58d96c023468fc1922d67764251b25e0 to your computer and use it in GitHub Desktop.
Using Values Submitted from HTML Form using Google Apps Script

Using Values Submitted from HTML Form using Google Apps Script

This is a sample script for using the values submitted from the HTML form using Google Apps Script and Javascript. In this case, the values include the files.

Issue

<form>
  Text: <input type="text" name="sampleText1" /><br />
  Single file: <input type="file" name="sampleFile1" /><br />
  <input
    type="submit"
    name="button"
    value="submit"
    onclick="main(this.parentNode)"
  />
</form>
<script>
  function main(e) {
    google.script.run.sample(e);
  }
</script>

This is a simple sample script for sending the values of form to Google Apps Script. In this case, texts and file are sent. When the button is clicked, main() is run. In this case, this.parentNode is sent to google.script.run.sample(this.parentNode). At that time, at Google Apps Script side, the text value can be correctly retrieved. But the file cannot be correctly sent. When the file is created as a file on Google Drive, the file is broken. I think that the reason of this issue might be due to character code.

So in this case, as the workaround, it is required to sent the file data as the string and byte array. I would like to propose for achieving this using the sample script.

Sample script

HTML & Javascript

<form>
  Text: <input type="text" name="sampleText1" /><br />
  Text: <input type="text" name="sampleText2" /><br />
  Textarea: <textarea name="sampleTextarea"></textarea><br />
  Number: <input type="number" name="sampleNumber" /><br />
  Date: <input type="date" name="sampleDate" /><br />
  Single file: <input type="file" name="sampleFile1" /><br />
  Multiple files: <input type="file" name="sampleFile2" multiple /><br />
  <input
    type="submit"
    name="button"
    value="submit"
    onclick="main(this);return false;"
  />
</form>
<div id="result"></div>

<script>
  const parseValues = async (e) =>
    Object.assign(
      ...(await Promise.all(
        [...e.parentNode].map(
          (obj) =>
            new Promise(async (res) => {
              const temp = { [obj.name]: { value: obj.value, type: obj.type } };
              if (obj.type == "file") {
                const files = obj.files;
                temp[obj.name].value = await (async (files) => {
                  return await Promise.all(
                    [...files].map(
                      (file) =>
                        new Promise((resolve, reject) => {
                          const fr = new FileReader();
                          fr.onload = (f) =>
                            resolve({
                              filename: file.name,
                              mimeType: file.type,
                              bytes: [...new Int8Array(f.target.result)],
                            });
                          fr.onerror = (err) => reject(err);
                          fr.readAsArrayBuffer(file);
                        })
                    )
                  );
                })(files).catch((err) => console.log(err));
              }
              res(temp);
            })
        )
      ))
    );

  async function main(e) {
    e.value = "clicked";
    const object = await parseValues(e);
    google.script.run
      .withSuccessHandler((f) => {
        document.getElementById("result").innerHTML = f;
      })
      .sample(object);
  }
</script>

Google Apps Script

function sample(object) {
  const formObj = Object.entries(object).reduce((o, [k, v]) => {
    let temp = { [k]: v.value };
    if (v.type == "file")
      temp[k] = v.value.map((e) =>
        Utilities.newBlob(e.bytes, e.mimeType, e.filename)
      );
    Object.assign(o, temp);
    return o;
  }, {});
  return "Done.";
}
  • In this sample script, parentNode from the form is parsed and the files are converted to the byte array (int8Array). And then, the values are sent to Google Apps Script side using google.script.run.

Result

When above script is run and the submit button is clicked after the values and files were inputted, the following values can be retrieved as formObj at Google Apps Script side. In this case, when Blob is created as a file, the inputted file is created.

{
  "sampleFile2": [Blob, Blob],
  "button": "clicked",
  "sampleNumber": "1",
  "sampleTextarea": "texts",
  "sampleFile1": [Blob],
  "sampleText1": "text1",
  "sampleText2": "text2",
  "sampleDate": "2000-01-01"
}

Note

  • When you use this script, please enable V8 runtime at the script editor.

Limitation

  • In this case, at Google Apps Script, the maximum size of blob, which can create a file, is 50 MB. So please be careful this.

Reference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment