问题
The Google Drive web interface allows you to download a single .zip file if you download a directory. However, I find no way to do that with the API. Is it possible to create a multi file zip on drive with the API?
Update: Tanakie's code works! This is great! However, I'm only able to get it working in my personal account. I have two G-Suite admin accounts and I get the error:
"Sorry, unable to open the file at this time.
Please check the address and try again."
I have confirmed this works fine in multiple free personal google accounts. Any idea why it will not work when using a paid google account?
------- UPDATE ------
If you get the "Sorry, unable to open the file at this time" error, wait a day, that error will fix itself.
Here's my final solution only with a POST. Pretty much as Tanaike says below.
Google Script:
function doPost(e) {
var zipFileName = e.parameter.zipFileName
var fileIds = e.parameter.ids.split(",");
return ContentService.createTextOutput(zipping(fileIds, zipFileName));
}
function zipping(fileIds, zipfilename) {
var blobs = [];
var mimeInf = [];
var accesstoken = ScriptApp.getOAuthToken();
fileIds.forEach(function(fileID) {
try {
var file = DriveApp.getFileById(fileID);
var mime = file.getMimeType();
var name = file.getName();
} catch (er) {
return er
}
var blob;
if (mime == "application/vnd.google-apps.script") {
blob = UrlFetchApp.fetch("https://script.google.com/feeds/download/export?id=" + fileID + "&format=json", {
method: "GET",
headers: {"Authorization": "Bearer " + accesstoken},
muteHttpExceptions: true
}).getBlob().setName(name);
} else if (~mime.indexOf('google-apps')) {
mimeInf =
mime == "application/vnd.google-apps.spreadsheet" ? ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", name + ".xlsx"] : mime == "application/vnd.google-apps.document" ? ["application/vnd.openxmlformats-officedocument.wordprocessingml.document", name + ".docx"] : mime == "application/vnd.google-apps.presentation" ? ["application/vnd.openxmlformats-officedocument.presentationml.presentation", name + ".pptx"] : ["application/pdf", name + ".pdf"];
blob = UrlFetchApp.fetch("https://www.googleapis.com/drive/v3/files/" + fileID + "/export?mimeType=" + mimeInf[0], {
method: "GET",
headers: {"Authorization": "Bearer " + accesstoken},
muteHttpExceptions: true
}).getBlob().setName(mimeInf[1]);
} else {
blob = UrlFetchApp.fetch("https://www.googleapis.com/drive/v3/files/" + fileID + "?alt=media", {
method: "GET",
headers: {"Authorization": "Bearer " + accesstoken},
muteHttpExceptions: true
}).getBlob().setName(name);
}
blobs.push(blob);
});
var zip = Utilities.zip(blobs, zipfilename);
var driveFolder = DriveApp.getFoldersByName("zipFiles").next();
return driveFolder.createFile(zip).getId();
}
php code to call it:
$url = 'https://script.google.com/a/domain.com/macros/s/### script id ####/exec';
$googleIDs = array();
foreach($documents AS $document){
$googleIDs[] = $document->google_file_id;
}
$data['zipFileName'] = date('c') . ".zip";
$data['ids'] = join(',', $googleIDs);
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, array( "Content-type: multipart/form-data" ));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$result = curl_exec($ch); // This returns the Google file ID of the zip file.
curl_close($ch);
HOWEVER, As in my comment below, this was a useless, futile exercise as Google limits files created by scripts to 10M. I'm off to find a solution that does not depend on Google... Wish I'd known that before I started.
回答1:
How about this workaround?
Unfortunately, there are no APIs for directly creating a zip file from outside in Google APIs. But I think that there is a workaround. There is zip()
method of Class Utilities in Google Apps Script (GAS). And there is Web Apps as a service for using GAS from outside. I think that what you want to do can be achieved by combining them.
Flow :
- Create a GAS script for creating zip files using
zip()
method of Class Utilities. - Deploy the script as Web Apps.
- You can launch the script from outside using GET and POST method of your applications. When you access Web Apps, also you can give some parameters and data.
Reference :
- zip() method in Class Utilities
- Web Apps
If this was not useful for you, I'm sorry.
Edit :
How about a following sample script? This is a simple sample script for creating a zip file for files in a folder.
- When Google Docs of Spreadsheet, Document and Slide are included in the folder, they are converted to Excel, Word and Powerpont format, respectively.
- When standalone scripts are included in a folder, they are converted to text data.
- Other types (images, text data and so son) are not converted.
These are the same to the web interface.
In order to use this script
Please do the following flow.
- Copy and paste the sample script to the script editor. And save it.
- Deploy Web Apps
- On script editor
- Publish -> Deploy as web app
- At "Project version", create new version.
- At "Execute the app as:", select "Me".
- At "Who has access to the app:", select "Anyone, even anonymous".
- Click Deploy button.
- On script editor
- Test the Web Apps using curl command as follows.
- If you can get the file ID of created zip file, it means that the script works.
Sample script :
function doGet(e) {
var files = DriveApp.getFolderById(e.parameter.folderid).getFiles();
var fileIds = [];
while (files.hasNext()) {
fileIds.push(files.next().getId());
}
return ContentService.createTextOutput(zipping(fileIds));
}
function zipping(fileIds) {
var zipfilename = "sample.zip";
var blobs = [];
var mimeInf = [];
var accesstoken = ScriptApp.getOAuthToken();
fileIds.forEach(function(e) {
try {
var file = DriveApp.getFileById(e);
var mime = file.getMimeType();
var name = file.getName();
} catch (er) {
return er
}
var blob;
if (mime == "application/vnd.google-apps.script") {
blob = UrlFetchApp.fetch("https://script.google.com/feeds/download/export?id=" + e + "&format=json", {
method: "GET",
headers: {"Authorization": "Bearer " + accesstoken},
muteHttpExceptions: true
}).getBlob().setName(name);
} else if (~mime.indexOf('google-apps')) {
mimeInf =
mime == "application/vnd.google-apps.spreadsheet" ? ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", name + ".xlsx"] : mime == "application/vnd.google-apps.document" ? ["application/vnd.openxmlformats-officedocument.wordprocessingml.document", name + ".docx"] : mime == "application/vnd.google-apps.presentation" ? ["application/vnd.openxmlformats-officedocument.presentationml.presentation", name + ".pptx"] : ["application/pdf", name + ".pdf"];
blob = UrlFetchApp.fetch("https://www.googleapis.com/drive/v3/files/" + e + "/export?mimeType=" + mimeInf[0], {
method: "GET",
headers: {"Authorization": "Bearer " + accesstoken},
muteHttpExceptions: true
}).getBlob().setName(mimeInf[1]);
} else {
blob = UrlFetchApp.fetch("https://www.googleapis.com/drive/v3/files/" + e + "?alt=media", {
method: "GET",
headers: {"Authorization": "Bearer " + accesstoken},
muteHttpExceptions: true
}).getBlob().setName(name);
}
blobs.push(blob);
});
var zip = Utilities.zip(blobs, zipfilename);
return DriveApp.createFile(zip).getId();
}
Sample curl command :
curl -L "https://script.google.com/macros/s/#####/exec?folderid=### folder ID ###"
Note :
- If you modified the script, please redeploy Web Apps as a new version. By this, the latest script is reflected.
- As a limitation of the sample script, this sample script checks only files in a folder. If you want to retrieve folders in a folder, you can see the sample script here.
- After you got the file ID of created ZIP file, you can download it using Drive API as you know.
If this was useful for you, I'm glad.
来源:https://stackoverflow.com/questions/46918380/is-there-a-way-to-create-a-zip-file-from-multiple-files-on-google-drive-with-the