Search code examples
htmlformsuploadgoogle-drive-api

Upload / Naming folders to a destination folder on Google Drive using Google Apps Script


My skills in coding/scripting are limited, please bear with me on incorrect terminologies; I need people to input three values on the form, [Objectives, Goals, and Remarks] followed by uploading an attachment (s) to my Google Drive. The script that I found (attached below) is working but needs to be adjusted (edited) for my needs. Please, I need help with the following:

  1. Right now, the files when uploaded, proceed to the default Google Drive folder. But I need them to be directed to a folder that I named, UPLOADS on my Google Drive.

  2. Each uploaded file to create the same folder name at the destination, e.g., a .pdf FILE with the name "Fountain" when uploaded, to create a FOLDER with the name "Fountain" in the destination folder.

3.The upload progress bar is working fine, but I would prefer the page to refresh after each submission, so the information on the form disappears.

*The input values on the form [Objectives, Goals, and Remarks] are not being recorded anywhere, after each submission - they are not on Google sheet; Any suggestions to solve this are welcome.

Thank you.

<!DOCTYPE html>
<html>
<body>
  <div id="formcontainer">

    <label for="myForm">2020 Vision:</label>

    <br><br>


    <form id="myForm"> 
      <label for="myForm">Information:</label>
      <div>
        <input type="text" name="objectives" placeholder=“Objectives:”>
      </div>
      <div>
        <input type="text" name="goals" placeholder=“Goals:”>
      </div>
      <div>

      <label for="fileText">Remarks:</label>

          <TEXTAREA name="projectDescription" 
          placeholder="Describe your attachment(s) here:"
          style ="width:400px; height:200px;"
          ></TEXTAREA>


      </div> 
      <br>


      <label for="attachType">Choose Attachment Type:</label>
      <br>
      <select name="attachType">
        <option value="Pictures Only">Picture(s)</option>
        <option value="Proposals Only">Documents</option>
        <option value="Pictures & Proposals">All</option>
      </select>
      <br>

      <label for="myFile">Upload Attachment(s):</label>
      <br>


      <input type="file" name="filename" id="myFile" multiple>

      <input type="button" value="Submit" onclick="iteratorFileUpload()">


    </form>
  </div>

  <div id="output"></div>
<div id="progressbar">
    <div class="progress-label"></div>
</div>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>

<script>

var numUploads = {};
numUploads.done = 0;
numUploads.total = 0;
folderName;

// Upload the files into a folder in drive
// This is set to send them all to one folder (specificed in the .gs file)
function iteratorFileUpload() {
    folderName = "Batch: "+new Date();
    var allFiles = document.getElementById('myFile').files;

    if (allFiles.length == 0) {
        alert('No file selected!');
    } else {
        //Show Progress Bar

        numUploads.total = allFiles.length;
        $('#progressbar').progressbar({
        value : false
        });//.append("<div class='caption'>37%</div>");
        $(".progress-label").html('Preparing files for upload');
        // Send each file at a time
        for (var i = 0; i < allFiles.length; i++) {
            console.log(i);
            sendFileToDrive(allFiles[i]);
        }
    }
}

function sendFileToDrive(file) {
    var reader = new FileReader();
    reader.onload = function (e) {
        var content = reader.result;
        console.log('Sending ' + file.name);
        var currFolder = ‘UPLOADS’; // my desired destination folder
        google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, folderName);
    }
    reader.readAsDataURL(file);
}

function updateProgressbar( idUpdate ){
   console.log('Received: ' + idUpdate);
   numUploads.done++;
   var porc = Math.ceil((numUploads.done / numUploads.total)*100);
   $("#progressbar").progressbar({value: porc });
   $(".progress-label").text(numUploads.done +'/'+ numUploads.total);
   if( numUploads.done == numUploads.total ){
      //uploadsFinished();
      numUploads.done = 0;
   };
}
</script>

  <script>
    function fileUploaded(status) {
      document.getElementById('myForm').style.display = 'none';
      document.getElementById('output').innerHTML = status;
    }

  </script>

  <style>
    body {
      max-width: 400px;
      padding: 20px;
      margin: auto;
    }
    input {
      display: inline-block;
      width: 100%;
      padding: 5px 0px 5px 5px;
      margin-bottom: 10px;
      -webkit-box-sizing: border-box;
      ‌​ -moz-box-sizing: border-box;
      box-sizing: border-box;
    }
    select {
      margin: 5px 0px 15px 0px;
    }
    input[type="submit"] {
      width: auto !important;
      display: block !important;
    }
    input[type="file"] {
      padding: 5px 0px 15px 0px !important;
    }
#progressbar{
    width: 100%;
    text-align: center;
    overflow: hidden;
    position: relative;
    vertical-align: middle;

}
.progress-label {
      float: left;
margin-top: 5px;
      font-weight: bold;
      text-shadow: 1px 1px 0 #fff;
          width: 100%;
    height: 100%;
    position: absolute;
    vertical-align: middle;
    }
  </style>
</body>

function doGet() {
  return HtmlService.createHtmlOutputFromFile('form')
    .setSandboxMode(HtmlService.SandboxMode.IFRAME);
}

function uploadFileToDrive(base64Data, fileName, folderName) {
  try{
    var splitBase = base64Data.split(','),
        type = splitBase[0].split(';')[0].replace('data:','');

    var byteCharacters = Utilities.base64Decode(splitBase[1]);
    var ss = Utilities.newBlob(byteCharacters, type);
    ss.setName(fileName);

    var dropbox = folderName || "UPLOADS"; //my desired destination for uploads
    var folder, folders = DriveApp.getFoldersByName(dropbox);

    if (folders.hasNext()) {
      folder = folders.next();
    } else {
      folder = DriveApp.createFolder(dropbox);
    }
    var file = folder.createFile(ss);

    return file.getName();
  }catch(e){
    return 'Error: ' + e.toString();
  }
}


Solution

  • I made some little changes to your code:

    HTML file

    in your "sendFileToDrive" I passed the folder name (in this case "Uploads") to your "uploadFileToDrive" in your Apps Script.

    function sendFileToDrive(file) {
        var reader = new FileReader();
        reader.onload = function (e) {
            var content = reader.result;
            console.log('Sending ' + file.name);
            // set the file's name where you want to set your files 
            var folderName = "UPLOADS"; // my desired destination folder
            google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, folderName);
        }
        reader.readAsDataURL(file);
    }
    

    To reset the values in your form after submitting it you can do it in the following way (Keep in mind this is vanilla JS, so there are several ways on the Internet to achieve this).

    Write this line of code document.getElementById("myForm").reset(); in your "updateProgressbar"

    function updateProgressbar( idUpdate ){
       console.log('Received: ' + idUpdate);
       numUploads.done++;
       var porc = Math.ceil((numUploads.done / numUploads.total)*100);
       $("#progressbar").progressbar({value: porc });
       $(".progress-label").text(numUploads.done +'/'+ numUploads.total);
       if( numUploads.done == numUploads.total ){
          //uploadsFinished();
          numUploads.done = 0;
          // Reset the form's fields values
          document.getElementById("myForm").reset();
    
       };
    }
    

    Apps Script file

    In your Apps Script code, I made these changes to create the folder from the file you just uploaded and then putting it in your "Uploads" folder. The problem you were having is you were trying to create a new folder in your if-else, but with the condition you had, you were not going to enter to the part of the code to create the folder.

    function doGet() {
      return HtmlService.createHtmlOutputFromFile('form')
        .setSandboxMode(HtmlService.SandboxMode.IFRAME);
    }
    
    function uploadFileToDrive(base64Data, fileName, folderName) {
      try{
        var splitBase = base64Data.split(','),
            type = splitBase[0].split(';')[0].replace('data:','');
    
        var byteCharacters = Utilities.base64Decode(splitBase[1]);
        var ss = Utilities.newBlob(byteCharacters, type);
        ss.setName(fileName);
        
        // Get your Uploads folder
        var folders = DriveApp.getFoldersByName(folderName);
        
        // Regex for splitting the file's extention like .pdf
        var patt1 = /\.[0-9a-z]+$/i;
        
        if (folders.hasNext()) {
          var folder = folders.next();
          // Create a folder with the name of the file you just uploaded in your root path
          // DriveApp.createFolder(fileName.split(patt1)[0]);
          // Create the file in your Uploads folder and a folder
          var file = folder.createFile(ss);
          folder.createFolder(fileName.split(patt1)[0]);
          return file.getName(); 
        } else return null;
        
      } catch(e){
        return 'Error: ' + e.toString();
      }
    }
    
    

    EDIT

    Notice the class folder has a special method called createFolder(name), which will allow you to create a folder in the currently folder you are handling as I put it in my Updated code. Check the Updated Docs links for more info.

    Docs

    I used these docs to help you find the solution to your problem: