I'm trying to convert a Docs file to PDF in GAS, using Drive API.
Based on what I found, basically the steps are:
- Get the Docs file
- Convert to PDF
- 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!
CodePudding user response:
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.