0

I'm trying to convert a Docs file to PDF in GAS, using Drive API.

Based on what I found, basically the steps are:

  1. Get the Docs file
  2. Convert to PDF
  3. Upload to Drive

What I did was use the 'export' function to get the Docs and convert it to PDF, then 'create' function to upload. My code below:

function test(){
  let service = getOAuthService();
  service.reset();

  // Get the Docs file
  let url = encodeURI("https://www.googleapis.com/drive/v3/files/<id of file>/export?mimeType=application/pdf&supportsAllDrives=true");

  let docFile = getGoogleAPI(url);

  var fileName = "my-test-file.pdf";
  var fileContent = docFile.getBlob();

  var fileMetadata = {
    name: fileName,
    parents: ["<id of parent folder>"],
    mimeType: "application/pdf"
  };

  url = "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&supportsAllDrives=true";

  var header = {
    "Authorization": "Bearer " +  service.getAccessToken(),
    "Content-Type": "multipart/related; boundary=<BOUNDARY_STRING>"
  };

  var body = "--<BOUNDARY_STRING>\r\n" +
             "Content-Type: application/json; charset=UTF-8\r\n\r\n" +
             JSON.stringify(fileMetadata) + "\r\n" +
             "--<BOUNDARY_STRING>\r\n" +
             "Content-Type: application/pdf\r\n\r\n" +
             fileContent + "\r\n" +
             "--<BOUNDARY_STRING>--";

  let response = UrlFetchApp.fetch(url, {
    method: "post",
    headers: header,
    payload: body,
    muteHttpExceptions: true
  });

  var responseJson = JSON.parse(response.getContentText());

  if (response.getResponseCode() == 200) {
    Logger.log("File uploaded successfully with ID: " + responseJson.id);
  } else {
    Logger.log("Error uploading file: " + responseJson.error.message);
  }
}

However the generate PDF file is either empty or not in the correct PDF format (cannot preview).

I think the first part (getting the Docs file using export) works, but it's the uploading that has the problem. Maybe an incorrect encoding?

Does anyone know where I am wrong on this?

Thanks in advance!

1 Answer 1

2

In your script, fileContent is Blob. Unfortunately, Blob cannot be directly used in this request body. I think that this is the reason for your current issue. In this case, how about the following modification?

Pattern 1:

When your request body is modified, please modify it as follows.

From:

"Content-Type: application/pdf\r\n\r\n" +
fileContent + "\r\n" +

To:

"Content-Transfer-Encoding: base64\r\n\r\n" +
Utilities.base64Encode(fileContent.getBytes()) + "\r\n" +
  • In your script, you are using text data as the request body. So, I used the above modification.

Pattern 2:

As another pattern, when your fileContent of Blob is directly used in the request body, please modify it as follows.

From:

var header = {
  "Authorization": "Bearer " +  service.getAccessToken(),
  "Content-Type": "multipart/related; boundary=<BOUNDARY_STRING>"
};

var body = "--<BOUNDARY_STRING>\r\n" +
           "Content-Type: application/json; charset=UTF-8\r\n\r\n" +
           JSON.stringify(fileMetadata) + "\r\n" +
           "--<BOUNDARY_STRING>\r\n" +
           "Content-Type: application/pdf\r\n\r\n" +
           fileContent + "\r\n" +
           "--<BOUNDARY_STRING>--";

let response = UrlFetchApp.fetch(url, {
  method: "post",
  headers: header,
  payload: body,
  muteHttpExceptions: true
});

To:

let response = UrlFetchApp.fetch(url, {
  payload: {
    metadata: Utilities.newBlob(JSON.stringify(fileMetadata), "application/json"),
    file: fileContent,
  },
  headers: { authorization: "Bearer " + service.getAccessToken() },
  muteHttpExceptions: true
});
  • In this case, the structure of multipart/form-data is automatically created on the internal server side.
  • This modification can obtain the same result as the above one.

Note:

  • In this modification, it supposes that your value of fileContent is the correct blob, and also, it supposes that your access token of "Bearer " + service.getAccessToken() can be used for uploading the file to Google Drive. Please be careful about this.

Reference:

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.