share
Stack Overflowusing Google Apps Script: how to convert/export a Drive file?
[+4] [6] wivku
[2017-03-19 14:10:24]
[ google-apps-script google-drive-api ]
[ https://stackoverflow.com/questions/42887569/using-google-apps-script-how-to-convert-export-a-drive-file ]

I would like to export a native Google spreadsheet/document/drawing/presentation file to another format, in that same folder, using Google Apps Script. I have enabled Advanced Drive Service [1], and looked at the instructions to Open and Convert Google Docs in your app [2].

Was hoping I could use Export [3] to get a File [4] which I could then save/rename using Insert [5].

Trying to achieve something like:

var file = {fileId: "1yDe...lD2U", 
            folderId: "0B_...hZ1k", 
            mimetype:"application/vnd.google-apps.document", 
            targetMimetype:"application/pdf", 
            targetName:"my converted document"}
var newFile = Drive.Files.export(file.fileId, file.targetMimetype)

// results in error message:
// "Export requires alt=media to download the exported content."

// I am sure the above is incomplete, but unsure how to actually
// save the exported file, in the correct location, with correct filename

Update: when adding alt=media to the call (var newFile = Drive.Files.export(file.fileId, file.targetMimetype, {alt: "media"})), then the script exits with error code 200 and shows the PDF content in the error message. Similar to issue 6573 [6].

Update: this may not have been clear enough, I want to convert from/to all of the formats listed in the Advanced Drive [7] page, not just to PDF. And the DriveApp getAs [8] documentation states that DriveApp can convert mostly to PDF and images. Hence the focus on using Advanced Drive instead of DriveApp.

Any reason you cannot use app script native functions like so: var blob = DriveApp.getFileById(file.fileId).getAs('application/pdf') and DriveApp.getFolderById(file.folderId).createFile(blob) to create your newPdfFile? - Jack Brown
Good point. Should work for PDF exports. I need to convert to all formats listed in the "Open and Convert Google Docs in your app" though. developers.google.com/apps-script/reference/drive/… states: the MIME type to convert to. For most blobs, 'application/pdf' is the only valid option. For images in BMP, GIF, JPEG, or PNG format, any of 'image/bmp', 'image/gif', 'image/jpeg', or 'image/png' are also valid. - wivku
[+5] [2017-03-21 11:32:47] wivku [ACCEPTED]

As a workaround I now use the OAuth2 library and the direct Drive API.

// ---------------------------------------------------------------------------------------------------
function testConvert() {
  var file = {
    id: "1cpAZp...I7ejZW1idk", // Google Sheet
    folderId: "0B_...Z1k", // test folder
  }

  convert(file, "pdf", "application/pdf");
  convert(file, "csv", "text/csv");
  convert(file, "xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
}

// ---------------------------------------------------------------------------------------------------
function convert(file, extension, targetMimeType) {
  var exportDetails = {
    targetMimeType: targetMimeType || "application/pdf",
    extension: extension || "pdf",
    postfix: "CONVERTED_FROM_GOOGLE_DOC",
  }

  // http://stackoverflow.com/questions/42887569/using-google-apps-script-how-to-convert-export-a-drive-file
  // https://code.google.com/p/google-apps-script-issues/issues/detail?id=6573

  // var blob = Drive.Files.export(file.id, exportDetails.targetMimeType, {alt: "media"})
  /*
    results in error 200 + content of converted file
    documentation https://developers.google.com/drive/v2/reference/files/export
    1) does not mention the {alt:"media"} (and without it the error is: "export requires alt=media to download the exported content")
    2) states the output is a Files resource (not a blob)
  */

  // using alternative: OAuth2 + public API
  // https://github.com/googlesamples/apps-script-oauth2
  var driveService = getDriveService();
  if (!driveService.hasAccess()) {
    showSidebar();
    return;
  }

  var accessToken = driveService.getAccessToken();
  var url = "https://www.googleapis.com/drive/v2/files/"+file.id+"/export?mimeType="+ exportDetails.targetMimeType
  var blob = UrlFetchApp.fetch(url, {
    headers: {
      Authorization: 'Bearer ' + driveService.getAccessToken()
    }
  });

  var resource = {
    title: DriveApp.getFileById(file.id).getName() +" "+ exportDetails.postfix +"."+ exportDetails.extension,
    description: "This is a converted document",
    mimeType: exportDetails.targetMimeType,
    parents: [{
      "kind": "drive#parentReference",
      "id": file.folderId,
      //"selfLink": string,
      //"parentLink": string,
      "isRoot": false
    }],
  }

  try {
    var convertedFile = Drive.Files.insert(resource, blob);
    Logger.log('ID: %s, File size (bytes): %s', convertedFile.id, convertedFile.fileSize);

  } catch(e) {
    Logger.log(e)
  }
}

1
[+1] [2017-03-19 23:39:27] ReyAnthonyRenacia

Try to tweak this code [1] from Armit Agarwal. The important bits to exporting your drive file to PDF is this part of code:

var blob = DriveApp.getFileById(ss.getId()).getAs("application/pdf");

  blob.setName(ss.getName() + ".pdf"); 

Then you can send it to your email by attaching the pdf file:

// If allowed to send emails, send the email with the PDF attachment
  if (MailApp.getRemainingDailyQuota() > 0) 
    GmailApp.sendEmail(email, subject, body, {
      htmlBody: body,
      attachments:[blob]     
    });  

Check the guide for additional reference.

[1] https://ctrlq.org/code/19869-email-google-spreadsheets-pdf

Agreed, for conversion to only PDF DriveApp is sufficient. I need to convert to other formats as well, e.g. Word/Excel. - wivku
2
[+1] [2019-07-21 17:33:02] Leonidas A

Here is the proper solution from https://issuetracker.google.com/issues/36765129#comment8, by a Google person.

Files.export() was recently added to the Drive v2 API, but an alternative is to use the older File.exportLinks field instead. Here's an example:

function convertToDocx(documentId) { 
  var file = Drive.Files.get(documentId); 
  var url = file.exportLinks['application/vnd.openxmlformats-officedocument.wordprocessingml.document']; 
  var oauthToken = ScriptApp.getOAuthToken(); 
  var response = UrlFetchApp.fetch(url, { 
    headers: { 
      'Authorization': 'Bearer ' + oauthToken 
    } 
  }); 
  return response.getBlob(); 
}

3
[0] [2017-03-19 22:35:22] pinoyyid

You're very close. Just use the pdf content as one of the parts of a multipart insert/post.


Sounds promising. Would you happen to have a working example? I am not yet familiar with creating the multipart insert. - wivku
4
[0] [2022-05-10 20:34:12] Tyler

Here is my version that I got to work after trying numerous examples:

function convertToDocx(newdocumentId,folder) {
var fileInstance = DriveApp.getFileById(newdocumentId);
var fileName = fileInstance.getName();
var blob = fileInstance.getBlob();
        var resource = {
            title: fileName + '.docx',
            mimeType: MimeType.MICROSOFT_WORD,
            parents: [
            {
                id: folder
            }],
        };
 Drive.Files.insert(resource, blob,{ convert: true, supportsAllDrives: true });
}

5
[0] [2023-10-03 11:29:06] vstepaniuk
function exportFile() {
  var exportFormat = 'docx';
  var docUrl = <Your doc url>;
  var exportUrl = docUrl.replace(/^(.*)\/.*/,'$1/export?format=' + exportFormat);

  var parameters = {
    method: 'GET',
    headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() }
  };
  var blob = UrlFetchApp.fetch(exportUrl, parameters).getBlob();  //.setName('exportName' + '.' + exportFormat);
  DriveApp.createFile(blob);  
}

This doesn't require neither API nor even advanced service

For Slides to export separate slide as image I needed to share the doc for viewing. For Docs works like this.

The name of the downloaded blob is just export+format, so you'll need to rename the blob probably first


6