1

I'm building a custom "Google Forms"-form with a file upload function. The form uses a custom "Thankyou"-page (see 1st line: iframe).
I've found a file upload script that needs to run in the Google Script environment and it will upload files to my Google Drive.

Now I need to combine this upload script with my custom Google Form. But I don't know exactly how to achieve this because there actions that need to be combined and the file upload has to be completed first before going to the "Thank you" page.

I've tried to combine it which looks like the code below.

The form:

<iframe name="hidden_iframe" id="hidden_iframe" style="display:none;" onload="if(submitted)  { picUploadJs(myForm); }"></iframe>

<form id="myForm" action="https://docs.google.com/forms/d/e/xxx/formResponse" target="hidden_iframe" onsubmit="submitted=true;">
     <input placeholder="1234" name="entry.1234" id="user" type="text">
     <label for="user">User:</label>

     <input name="picToLoad" type="file" />

     <div id="status" style="display: none">
       Uploading. Please wait...
     </div

   <button type="submit" name="action">Send</button>
</form>

The upload script:

<script>

  function picUploadJs(frmData) {

    document.getElementById('status').style.display = 'inline';

    google.script.run
      .withSuccessHandler(updateOutput)
      .processForm(frmData)
    };

  function updateOutput() {

    var outputDiv = document.getElementById('status');
    outputDiv.innerHTML = "The File was UPLOADED!";
    window.location='https://thankyoupage/';
  }

</script>

This now results in: Form input data is submitted, upload status text appears but nothing happens: "Uploading. Please wait...".

The result should be: Form input data submit, upload file to drive and redirect to the thankyou page.

EDIT: Google Script code

function doGet(e) {
  return HtmlService.createTemplateFromFile('test')
    .evaluate() // evaluate MUST come before setting the Sandbox mode
    .setTitle('Name To Appear in Browser Tab')
    //.setSandboxMode();//Defaults to IFRAME which is now the only mode available
}

function processForm(theForm) {
  var fileBlob = theForm.picToLoad;

  Logger.log("fileBlob Name: " + fileBlob.getName())
  Logger.log("fileBlob type: " + fileBlob.getContentType())
  Logger.log('fileBlob: ' + fileBlob);

  var fldrSssn = DriveApp.getFolderById('xxxx');
    fldrSssn.createFile(fileBlob);

  return true;
}

5
  • Can I ask you about processForm() of Google Apps Script? Commented Apr 8, 2019 at 23:46
  • 1
    I've added the Google script code in my original post. Commented Apr 9, 2019 at 7:03
  • Thank you for replying. Before modify your script, I would like to confirm your current situation. In your current situation, when "Send" button is clicked, Google Form is submitted, picUploadJs() is run, and the file is created on Google Drive? Please tell me your current situation, when "Send" button is clicked. Commented Apr 9, 2019 at 8:46
  • When "Send" is clicked: Google Form is submitted, picUploadJs() runs but only partly: the element 'status' changes style to inline but the upload function google.script.run doesn't seem to start or run correctly. Commented Apr 9, 2019 at 9:36
  • 1
    Thank you for replying. I thought that I could understand your situation. So I proposed a modified script as an answer. Could you please confirm it? I'm not sure about your whole script. In my environment, I could confirm that the above modified script worked. But if the script didn't work in your environment, I apologize. Commented Apr 9, 2019 at 12:02

1 Answer 1

1
  • When you click "Send" button,
    • Google Form works fine.
    • document.getElementById('status').style.display = 'inline' works.
    • Function of processForm(frmData) at Google Apps Script doesn't work.
    • Function of updateOutput() at Javascript doesn't work.

If my understanding is correct, how about this modification? Please think of this as just one of several answers.

Modification points:

  • In this modification, the file was retrieved using onclick event, while the script for submitting to Google Form is not modified.
  • The retrieved file is converted to base64 and sent to Google Apps Script.

Modified script:

HTML:

<form id="myForm" action="https://docs.google.com/forms/d/e/xxx/formResponse" target="hidden_iframe" onsubmit="submitted=true;">
  <input placeholder="1234" name="entry.1234" id="user" type="text">
  <label for="user">User:</label>
  <input name="picToLoad" type="file" id="sampleFile" /> <!-- Modified -->
  <div id="status" style="display: none">
  Uploading. Please wait...
  </div>
  <button type="submit" name="action" id="sampleId" >Send</button> <!-- Modified -->
</form>

Javascript:

<script>
  // Below script was added.
  document.getElementById("sampleId").onclick = function(e) {
    e.stopPropagation();
    e.preventDefault();
    var file = document.getElementById("sampleFile").files[0];
    const f = new FileReader();
    f.onload = (e) => {
      const data = e.target.result.split(",");
      const obj = {fileName: file.name, mimeType: data[0].match(/:(\w.+);/)[1], data: data[1]};
      picUploadJs(obj);
    }
    f.readAsDataURL(file);
  };

  function picUploadJs(frmData) {
    document.getElementById('status').style.display = 'inline';
    google.script.run.withSuccessHandler(updateOutput).processForm(frmData)
  };

  function updateOutput() {
    var outputDiv = document.getElementById('status');
    outputDiv.innerHTML = "The File was UPLOADED!";
    window.location='https://thankyoupage/';
  }
</script>

Google Apps Script:

function processForm(theForm) {
  var fileBlob = Utilities.newBlob(Utilities.base64Decode(theForm.data), theForm.mimeType, theForm.fileName);
  var fldrSssn = DriveApp.getFolderById('xxxx');
  fldrSssn.createFile(fileBlob);
  return true;
}

Note:

  • When the file is selected and click a "Send" button, the file is send to Google Apps Script and is created as a file on Google Drive, while Google Form is submitted. Then updateOutput() at Javascript side is run.
  • In this modified script, The blob is used. So the maximum size of a file for uploading is 50 MB. Please be careful this.

Edit 1:

At your comment, it was found that When I remove the id=sampleId from the submit button, the Google Form data is submitted correctly. Using this, please test the following modification.

In this modification, id="sampleId" was removed and the event is triggered using the name of element.

HTML:

<form id="myForm" target="hidden_iframe" onsubmit="submitted=true;">
  <input placeholder="1234" name="entry.1234" id="user" type="text">
  <label for="user">User:</label>
  <input name="picToLoad" type="file" id="sampleFile" />
  <div id="status" style="display: none">
  Uploading. Please wait...
  </div>
  <button type="submit" name="action">Send</button> <!-- Modified -->
</form>

Javascript:

var button = document.getElementsByName('action')[0]; // Modified
button.onclick = function(e) { // Modified
  e.stopPropagation();
  e.preventDefault();
  var file = document.getElementById("sampleFile").files[0];
  const f = new FileReader();
  f.onload = (e) => {
    const data = e.target.result.split(",");
    const obj = {fileName: file.name, mimeType: data[0].match(/:(\w.+);/)[1], data: data[1]};
    picUploadJs(obj);
  }
  f.readAsDataURL(file);
};

Edit 2:

I updated HTML and Javascript. Please confirm it. Google Apps Script is not modified.

HTML:

<iframe name="hidden_iframe" id="hidden_iframe" style="display:none;" onload="if(submitted)  { picUploadJs(myForm); }"></iframe>
<form id="myForm" action="https://docs.google.com/forms/d/e/xxx/formResponse" target="hidden_iframe" onsubmit="submitted=true;">
  <input placeholder="1234" name="entry.1234" id="user" type="text">
  <label for="user">User:</label>
  <input name="picToLoad" type="file" id="sampleFile" /> <!-- Modified -->
  <div id="status" style="display: none">
  Uploading. Please wait...
  </div>
  <button type="submit" name="action">Send</button>
</form>

Javascript:

<script>
  // This function was modified.
  function picUploadJs(myForm) {
    var file = document.getElementById("sampleFile").files[0];
    const f = new FileReader();
    f.onload = (e) => {
      const data = e.target.result.split(",");
      const obj = {fileName: file.name, mimeType: data[0].match(/:(\w.+);/)[1], data: data[1]};
      document.getElementById('status').style.display = 'inline';
      google.script.run.withSuccessHandler(updateOutput).processForm(obj);
    }
    f.readAsDataURL(file);
  }

  function updateOutput() {
    var outputDiv = document.getElementById('status');
    outputDiv.innerHTML = "The File was UPLOADED!";
    window.location='https://thankyoupage/';
  }
</script>
Sign up to request clarification or add additional context in comments.

13 Comments

Thank you for taking your time to figure this whole thing out for me! I've modified my script with your changes, but unfortunately it now doesn't submit the Google Form data. It however does upload a file to Google Drive and redirects to Thank-you page. When I remove the id=sampleId from the submit button, the Google Form data is submitted correctly (but of course the upload function doesn't work anymore).
Did you maybe forget the iframe code? Because this line was also used in my original code: <iframe name="hidden_iframe" id="hidden_iframe" style="display:none;" onload="if(submitted) { picUploadJs(myForm); }"></iframe> I'm currently trying to make it work like this, but have not yet succeeded. <iframe name="hidden_iframe" id="hidden_iframe" style="display:none;" onload="if(submitted) { upload(); }"></iframe> And put your script into a function: function upload() { //your script };
Sorry, but it's still not sending the Form data. I think the file upload script is getting "more priority" (or is faster?) and skipping the action function from the <form> tag.
@Bldjef Thank you for replying and testing it. I apologize for the inconvenience. So I would like to confirm the situation and modify it. If you can give me a time to do, I'm glad.
@Bldjef I apologize for the inconvenience. I updated my answer. Could you please confirm it? In this modification, <iframe>...</iframe> was used again. By this, I could confirm that both submission can be done. If this didn't work, I apologize.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.