Search code examples
google-apps-scriptgoogle-drive-apigoogle-docs

Download file from a server to local machine via Google Docs Add-on - Apps Script


I need to modify my Apps Script Google Docs add-on project to download a file generated in our server (authentication needed) to the local machine. Didn't found a way to download that file directly into the local machine. So trying to download it first into the drive, then download the drive file into the local machine.

I have currently implemented to download that file into the Google Drive, now looking for a way to download it to the local machine. Searched for ways to do it with the Drive api. But didn't found a way yet.

The downloading file will be in below formats.

.pdf, .epub, .jpg, .png, .zip, .mobi, .indd

Found this article, but it is only for downloading text content.

This is my code for retrieving the file from our server, download it to the drive.

 function downloadOutput(selectedFile){
  var mimeType;
  var template = new Template();

  var documentProperties = PropertiesService.getDocumentProperties();
  var jobFolderPath = replaceWhiteSpace(documentProperties.getProperty('JOB_FOLDER_PATH'));
  var pathParts = jobFolderPath.split("/");
  var outputFolderName = pathParts.pop();
  var rootFolderID = getWriterRootFolder();

  var filename = replaceWhiteSpace(selectedFile);
  if (selectedFile.includes('.pdf')){
    mimeType = 'application/pdf';
  }
  else if(selectedFile.includes('.epub')){
    mimeType = 'application/epub+zip';
  }
  else if (selectedFile.includes('.jpg')){
    mimeType = 'image/jpeg';
  }
  else if(selectedFile.includes('.png')){
    mimeType = 'image/png';
  }
  else if(selectedFile.includes('.zip')){
    mimeType= 'application/zip';
  }
  else if(selectedFile.includes('.mobi')){
    mimeType= 'application/x-mobipocket-ebook';
  }
  else if(selectedFile.includes('.indd')){ 
    mimeType = 'application/x-indesign';
  }

  //This is for retrieving the selectedFile from our server.  
  var response = sendRequest(template.server, template.customer, "/api/v2/","GET", "files" + jobFolderPath + "/"+ filename);

  var output = {
    title: selectedFile,
    parents: [{'id':rootFolderID}],
    mimeType: mimeType
  };

  var outputFile = Drive.Files.insert(output, response.getBlob());

  //some tries to get a download from the drive file, but not worked.
  var url = "https://www.googleapis.com/drive/v3/files/" + outputFile.id + "?alt=media&mimeType="+ mimeType;

  var blob = UrlFetchApp.fetch(url, {
    method: "get",
    headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
    muteHttpExceptions: true
  });

  var rrr = UrlFetchApp.fetch(outputFile.downloadUrl, 
  { 
    method :"get",
      headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()    }
  });
}

Please suggest a way to download the drive file to the 'Downloads' folder in local machine or download the server file directly into the local machine without saving it in the drive.

Thanks in advance.


Solution

  • As long as Apps Script is server side executed, there is no direct way to use it to download to your machine.

    But, as you have your file is in your Drive, what about using one of the client libraries for Google APIs, in your case Drive API, to download it directly to your machine?

    The steps are easy, look for the file, grab the ID and download to your machine.

    Google has specific guides for Download files, this includes Download a general file from Google Drive and Download Google Workspace Document, and for search for a specific file, via name = my_server_side_generated_file or mimeType = 'application/epub+zip', or whatever query method you want to use.

    This is the simple use case for downloading a file in Node.js , but you have examples also for Python and Java.

    var fileId = '0BwwA4oUTeiV1UVNwOHItT0xfa2M';
    var dest = fs.createWriteStream('/tmp/photo.jpg');
    drive.files.get({
      fileId: fileId,
      alt: 'media'
    })
        .on('end', function () {
          console.log('Done');
        })
        .on('error', function (err) {
          console.log('Error during download', err);
        })
        .pipe(dest);
    
    Documentation: