0

i'm using this script, which is described in this video to let people upload files to my Google Drive (in slightly modified version).

When uploading large files, there is no sign of progress. It will just say "File uploaded successfully" when finished. Is it possible to let the user know how long the upload will take? It does not has to be a status bar, percentage is also fine.

Thanks for any input to this case.

Code:

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

function uploadFiles(form) {
  
  try {
    
    var dropbox = "Work_Collector";
    var folder, folders = DriveApp.getFoldersByName(dropbox);
    
    if (folders.hasNext()) {
      folder = folders.next();
    } else {
      folder = DriveApp.createFolder(dropbox);
    }
    
    var blob = form.myFile;    
    var file = folder.createFile(blob);    
    file.setDescription("Uploaded by " + form.myName);
        
    return "File uploaded successfully " + file.getUrl();
    
  } catch (error) {
    
    return error.toString();
  }
  
}

HTML:

   <!doctype html>
<style type="text/css">
body {
    background-color: #FFFFFF;
}
</style>
<BR>
<BR>
<BR>
<div align="center">
  <p><img src="https://b627cc12-a-62cb3a1a-s-sites.googlegroups.com/site/imagehosting199/home/GoogleTeamColorSmall.png"></p>
  <table width="459" border="0">
    <tbody>
      <tr>
        <td width="462"><div align="center">
          <hr>
        </div>
          <form id="myForm" align="center">
            <input type="text" name="myName" placeholder="Your name..">
            <input type="file" name="myFile">
            <input type="submit" value="Upload File" 
           onclick="this.value='Uploading..';
                    google.script.run.withSuccessHandler(fileUploaded)
                    .uploadFiles(this.parentNode);
                    return false;">
          </form>
          <div id="output"></div>
          <script>
    function fileUploaded(status) {
        document.getElementById('myForm').style.display = 'none';
        document.getElementById('output').innerHTML = status;
    }
          </script>
        <style>
 input { display:block; margin: 20px; }
 
          </style>
        <hr></td>
      </tr>
    </tbody>
  </table>
  <h3>&nbsp;</h3>
  <p>&nbsp;</p>
</div>
dalleaux
  • 527
  • 5
  • 11
  • 2
    Please attach your code to the question. External links might not be available later and your question should be able to help other people with similar issues. See [this SO Meta post](https://meta.stackoverflow.com/questions/285551/why-should-i-not-upload-images-of-code-data-errors-when-asking-a-question) for an idea why this is problematic. – vinkomlacic Apr 25 '22 at 07:28
  • 2
    [This question](https://stackoverflow.com/questions/35343688/google-apps-script-file-upload-progress-indicator) might be a duplicate and has a clear answer. The answer is not accepted so I won't mark it as duplicate. – vinkomlacic Apr 25 '22 at 07:31
  • Does this answer your question? [Google Apps Script: file upload progress indicator](https://stackoverflow.com/questions/35343688/google-apps-script-file-upload-progress-indicator) – Rafa Guillermo Apr 25 '22 at 07:40
  • 1
    This library may help you. [ResumableUploadForGoogleDrive_js](https://github.com/tanaikech/ResumableUploadForGoogleDrive_js) – idfurw Apr 25 '22 at 07:51

1 Answers1

0

Issue and workaround:

Unfortunately, when a file is directly uploaded using google.script.run.withSuccessHandler(fileUploaded).uploadFiles(this.parentNode), the progress information cannot be retrieved. It seems that this is the current specification. This has already been mentioned in the comment from vinkomlacic and I hope this is helpful to you. And also, in this method, the maximum file size is 50 MB because of the limitation of the file Blob at Google Apps Script side. So, in order to upload a large file and show the progress information, it is required to use a workaround. In your situation, I also thought that a Javascript library of ResumableUploadForGoogleDrive_js might be able to be used. This has already been mentioned by idfurw's comment.

In this answer, I would like to achieve your goal using a Javascript library of ResumableUploadForGoogleDrive_js. In this case, I would like to propose a sample script by modifying this answer.

Usage

1. Create Google Apps Script for Web Apps.

In order to use Web Apps, please create a new Google Apps Script project.

2. Sample script.

Please copy and paste the following script to the script editor of the created Google Apps Script project.

Google Apps Script side: Code.gs

In this case, your showing script is modified.

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

function getAuth() {
  // DriveApp.createFile() // This is used for adding the scope of "https://www.googleapis.com/auth/drive".

  var dropbox = "Work_Collector";
  var folder, folders = DriveApp.getFoldersByName(dropbox);
  if (folders.hasNext()) {
    folder = folders.next();
  } else {
    folder = DriveApp.createFolder(dropbox);
  }
  return { accessToken: ScriptApp.getOAuthToken(), folderId: folder.getId() };
}

function setDescription({fileId, description}) {
  DriveApp.getFileById(fileId).setDescription(description);
}

HTML & Javascript side: form.html

In this case, your showing HTML form is modified.

<form id="myForm" align="center">
  <input type="text" name="myName" placeholder="Your name..">
  <input type="file" name="myFile">
  <input type="submit" value="Upload File"
           onclick="this.value='Uploading..';
                    run();
                    return false;">
</form>
<div id="progress"></div>
<div id="output"></div>

<script src="https://cdn.jsdelivr.net/gh/tanaikech/ResumableUploadForGoogleDrive_js@master/resumableupload_js.min.js"></script>
<script>
function run() {
  google.script.run.withSuccessHandler(accessToken => ResumableUploadForGoogleDrive(accessToken)).getAuth();
}

function ResumableUploadForGoogleDrive({accessToken, folderId}) {
  const myName = document.getElementsByName("myName")[0].value;
  const file = document.getElementsByName("myFile")[0].files[0];
  if (!file) return;
  let fr = new FileReader();
  fr.fileName = file.name;
  fr.fileSize = file.size;
  fr.fileType = file.type;
  fr.readAsArrayBuffer(file);
  fr.onload = e => {
    var id = "p";
    var div = document.createElement("div");
    div.id = id;
    document.getElementById("progress").appendChild(div);
    document.getElementById(id).innerHTML = "Initializing.";
    const f = e.target;
    const resource = { fileName: f.fileName, fileSize: f.fileSize, fileType: f.fileType, fileBuffer: f.result, accessToken, folderId };
    const ru = new ResumableUploadToGoogleDrive();
    ru.Do(resource, function (res, err) {
      if (err) {
        console.log(err);
        return;
      }
      console.log(res);
      let msg = "";
      if (res.status == "Uploading") {
        msg = Math.round((res.progressNumber.current / res.progressNumber.end) * 100) + "% (" + f.fileName + ")";
      } else {
        msg = res.status + " (" + f.fileName + ")";
      }
      if (res.status == "Done") {
        google.script.run.withSuccessHandler(_ => {
          document.getElementById('myForm').style.display = 'none';
          document.getElementById('p').style.display = 'none';
          document.getElementById('output').innerHTML = "https://drive.google.com/file/d/" + res.result.id + "/view?usp=drivesdk";
        }).setDescription({fileId: res.result.id, description: "Uploaded by " + myName});
      }
      document.getElementById(id).innerText = msg;
    });
  }
}
</script>

3. Enable Drive API.

Please enable Drive API at Advanced Google services.

4. Deploy Web Apps.

The detailed information can be seen at the official document. In this case, it supposes that you are using new IDE. Please be careful this.

  1. On the script editor, at the top right of the script editor, please click "click Deploy" -> "New deployment".
  2. Please click "Select type" -> "Web App".
  3. Please input the information about the Web App in the fields under "Deployment configuration".
  4. Please select "Me" for "Execute as".
    • This is the importance of this workaround.
  5. Please select "Anyone" for "Who has access".
    • For testing this script, I thought that this setting might be suitable.
  6. Please click "Deploy" button.
  7. Copy the URL of the Web App. It's like https://script.google.com/macros/s/###/exec.

5. Testing:

When this script is run, retrieve a text and a file, and the file is uploaded with the resumable upload. And, the file is put in a specific folder. And, the uploaded file has the description using the inputted text. During the file is uploaded, progress information is shown in the tag of progress as follows.

enter image description here

This is a simple sample script. So, if you want to use other progress information, please modify the above script.

Note:

  • In this case, the access token is retrieved from Google Apps Script side using ScriptApp.getOAuthToken(). For testing this script, you can use the scope of https://www.googleapis.com/auth/drive. But, if you want to keep the security when you use this script in your actual situation, I would like to propose to use https://www.googleapis.com/auth/drive.file as the scope. By this, the access token can access only the files created by this client.

  • When you modified the Google Apps Script, please modify the deployment as a new version. By this, the modified script is reflected in Web Apps. Please be careful this.

  • You can see the detail of this in the report of "Redeploying Web Apps without Changing URL of Web Apps for new IDE".

  • This is a simple sample script using your showing script. So, please modify this for your actual situation.

References:

Tanaike
  • 181,128
  • 11
  • 97
  • 165