April 20, 2019: GAS library for this situation was published. Please check it at https://github.com/tanaikech/FetchApp.
These sample scripts are for requesting multipart post using Google Apps Script.
In most cases, the multipart request is used for uploading files. So I prepared 2 sample situations as follows. For each situation, the request parameters are different.
- Upload a file from Google Drive to Slack.
- Convert an excel file to Spreadsheet on Google Drive using Drive API v3.
Multipart post is required for these situations.
In order to use this sample, please retrieve access token for uploading file to Slack.
If curl is used for this situation, the curl code becomes as follows. But this code uploads a file on local PC to Slack. The detail information is here.
curl -X POST -sSL \
-F token=### access token ### \
-F channels=### channel ID ### \
-F filename=### filename on Slack ### \
-F title=### title on Slack ### \
-F file=@### filename ### \
"https://slack.com/api/files.upload"
When above curl code is changed to GAS, the script becomes as follows.
function request_slack1() {
var fileId = "### file ID on Google Drive ###";
var metadata = {
token: "### access token ###",
channels: "### channel ID ###",
filename: "### filename on Slack ###",
title: "### title on Slack ###",
};
var url = "https://slack.com/api/files.upload";
var file = DriveApp.getFileById(fileId);
var boundary = "xxxxxxxxxx";
var data = "";
for (var i in metadata) {
data += "--" + boundary + "\r\n";
data += "Content-Disposition: form-data; name=\"" + i + "\"; \r\n\r\n" + metadata[i] + "\r\n";
}
data += "--" + boundary + "\r\n";
data += "Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getName() + "\"\r\n";
data += "Content-Type:" + file.getMimeType() + "\r\n\r\n";
var payload = Utilities.newBlob(data).getBytes()
.concat(file.getBlob().getBytes())
.concat(Utilities.newBlob("\r\n--" + boundary + "--").getBytes());
var options = {
method : "post",
contentType : "multipart/form-data; boundary=" + boundary,
payload : payload,
muteHttpExceptions: true,
};
var res = UrlFetchApp.fetch(url, options).getContentText();
Logger.log(res);
}
For uploading files to slack, following script can be also used.
function request_slack2(){
var fileId = "### file ID on Google Drive ###";
var url = "https://slack.com/api/files.upload";
var payload = {
token: "### access token ###",
channels: "### channel ID ###",
filename: "### filename on Slack ###",
title: "### title on Slack ###",
file: DriveApp.getFileById(fileId).getBlob(),
};
var options = {
method: "POST",
payload: payload,
muteHttpExceptions : true,
};
var res = UrlFetchApp.fetch(url, options).getContentText();
Logger.log(res)
}
If curl is used for this situation, the curl code becomes as follows. But this code uploads a file on local PC to Google Drive.
curl -X POST -sSL \
-H "Authorization: Bearer ### access token ###" \
-F "metadata={ \
name : '### uploaded filename on Google Drive ###', \
mimeType : 'application/vnd.google-apps.spreadsheet' \
};type=application/json;charset=UTF-8" \
-F "file=@### Excel file ###;type=application/vnd.ms-excel" \
"https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"
When above curl code is changed to GAS, the script becomes as follows.
In this sample, please be careful that contentType
is multipart/related
not multipart/form-data
. The detail information is here.
function request_driveapi() {
var fileId = "### file ID (excel file) on Google Drive ###";
var metadata = {
name: "### uploaded filename on Google Drive ###",
mimeType: "application/vnd.google-apps.spreadsheet"
};
var fields = "id,mimeType,name";
var url = "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields="
+ encodeURIComponent(fields);
var file = DriveApp.getFileById(fileId);
var boundary = "xxxxxxxxxx";
var data = "--" + boundary + "\r\n";
data += "Content-Disposition: form-data; name=\"metadata\"\r\n";
data += "Content-Type: application/json; charset=UTF-8\r\n\r\n";
data += JSON.stringify(metadata) + "\r\n";
data += "--" + boundary + "\r\n";
data += "Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getName() + "\"\r\n";
data += "Content-Type: " + file.getMimeType() + "\r\n\r\n";
var payload = Utilities.newBlob(data).getBytes()
.concat(file.getBlob().getBytes())
.concat(Utilities.newBlob("\r\n--" + boundary + "--").getBytes());
var options = {
method : "post",
contentType : "multipart/related; boundary=" + boundary,
payload : payload,
headers: {'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()},
muteHttpExceptions: true,
};
var res = UrlFetchApp.fetch(url, options).getContentText();
Logger.log(res);
}
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
And then, I analyzed logs from curl codes which were shown above.