1
votes

I've created a custom Google Form which allows a logged in Google user to include multiple files with the form. The files are uploaded into a newly created folder in Google Drive. The Google Script uses the current user's email address + current date and time as the folder name.

Problem and expected result:

Because of the forEach function, the script uploads each file into a separate folder (with the same name). I would like to upload each file of one form submission into one folder.

HTML:

<iframe name="hidden_iframe" id="hidden_iframe" style="display:none;" onload="if(submitted)  { picUploadJs(myForm); }"></iframe>
<form id="myForm" class="col s12" 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" />
  <div id="status" style="display: none">
  Uploading. Please wait...
  </div>
  <button type="submit" name="action">Send</button> <!-- Modified -->
</form>

Javascript:

 function picUploadJs(myForm) {
    const f = document.getElementById("files");
    [...f.files].forEach((file, i) => {
    const fr = new FileReader();
    fr.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);
    }
    fr.readAsDataURL(file);
    });
  }

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

Google Script:

function doGet(e) {
  Logger.log("doGet done");
  return HtmlService.createTemplateFromFile('test')
    .evaluate() // evaluate MUST come before setting the Sandbox mode
    .setTitle('Form')
    //.setSandboxMode();//Defaults to IFRAME which is now the only mode available
}

function processForm(theForm) {
  var dateTime = Utilities.formatDate(new Date(), "GMT+2", "dd-MM-yy_HH-mm");
  var email = Session.getActiveUser().getEmail();
  var parentFolder=DriveApp.getFolderById('xxxxx');  
  var newFolder=parentFolder.createFolder(email + "_" + dateTime);
  var newFolderId = DriveApp.getFoldersByName(newFolder).next().getId();

  var fileBlob = Utilities.newBlob(Utilities.base64Decode(theForm.data), theForm.mimeType, theForm.fileName);
  var fldrSssn = DriveApp.getFolderById(newFolderId);
  fldrSssn.createFile(fileBlob);
  return true;
}
1

1 Answers

1
votes
  • When the files are submitted, you want to create one new folder every submitting.
  • You want to upload multiple files to the created folder.

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

Modified scripts:

HTML:

Please modify as follows.

<input name="picToLoad" type="file" id="sampleFile" />
<input name="picToLoad" type="file" id="files" multiple />

Javascript:

Please modify picUploadJs().

function picUploadJs(myForm) {
  const f = document.getElementById("files");
  google.script.run.withSuccessHandler((folderId) => { // Added
    var files = [...f.files];
    files.forEach((file, i) => {
      const fr = new FileReader();
      fr.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(() => {
          if (i == files.length - 1) updateOutput();
        }).processForm(obj, folderId); // Modified
      }
      fr.readAsDataURL(file);
    });
  }).createFolder();
}

Google Apps Script:

I separated processForm() to processForm() and createFolder().

// Added
function createFolder() {
  var dateTime = Utilities.formatDate(new Date(), "GMT+2", "dd-MM-yy_HH-mm");
  var email = Session.getActiveUser().getEmail();
  var parentFolder = DriveApp.getFolderById('xxxxx');
  var newFolder = parentFolder.createFolder(email + "_" + dateTime);
  var newFolderId = DriveApp.getFoldersByName(newFolder).next().getId();
  return newFolderId;
}

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

Note:

  • In your HTML, the top line is as follows.

    <form id="myForm" target="hidden_iframe" onsubmit="submitted=true;">
    

    From your previous question, if you are using the following lines, please update your question. I supposed that you are using the following script.

    <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;">
    

If this was not the result you want, I apologize.