14

我在 Google Drive 文件夹中有一个文件夹,其中包含几个文件。我想制作一个 Google Apps 脚本,它将压缩该文件夹中的所有文件并在同一文件夹中创建 zip 文件。

我找到了一个有Utilities.zip()功能的视频,但没有 API 参考。我该如何使用它?提前致谢。

4

5 回答 5

15

实际上它比这更容易。文件已经是 Blob(任何具有 getBlob() 的东西都可以传递给任何需要 Blob 的函数)。所以代码看起来像这样:

var folder = DocsList.getFolder('path/to/folder');
folder.createFile(Utilities.zip(folder.getFiles(), 'newFiles.zip'));

此外,如果您在文件夹中有多个具有相同名称的文件,它将不起作用... Google Drive 文件夹支持,但 Zip 文件不支持。

要使其适用于具有相同名称的多个文件:

var folder = DocsList.getFolder('path/to/folder');
var names = {};
folder.createFile(Utilities.zip(folder.getFiles().map(function(f){
  var n = f.getName();
  while (names[n]) { n = '_' + n }
  names[n] = true;
  return f.getBlob().setName(n);
}), 'newFiles.zip'));
于 2012-11-07T03:09:48.603 回答
12

正如DocsList已弃用的那样,您可以使用以下代码压缩包含文件和子文件夹的整个文件夹,并保持其结构:

var folder = DriveApp.getFolderById('<YOUR FOLDER ID>');
var zipped = Utilities.zip(getBlobs(folder, ''), folder.getName()+'.zip');
folder.getParents().next().createFile(zipped);

function getBlobs(rootFolder, path) {
  var blobs = [];
  var files = rootFolder.getFiles();
  while (files.hasNext()) {
    var file = files.next().getBlob();
    file.setName(path+file.getName());
    blobs.push(file);
  }
  var folders = rootFolder.getFolders();
  while (folders.hasNext()) {
    var folder = folders.next();
    var fPath = path+folder.getName()+'/';
    blobs.push(Utilities.newBlob([]).setName(fPath)); //comment/uncomment this line to skip/include empty folders
    blobs = blobs.concat(getBlobs(folder, fPath));
  }
  return blobs;
}

getBlobs函数将文件夹中的所有文件组成一个数组,并将每个文件名更改为其相对路径,以在压缩时保持结构。

要压缩包含多个同名项目的文件夹,请使用此getBlob函数:

function getBlobs(rootFolder, path) {
  var blobs = [];
  var names = {};
  var files = rootFolder.getFiles();
  while (files.hasNext()) {
    var file = files.next().getBlob();
    var n = file.getName();
    while(names[n]) { n = '_' + n }
    names[n] = true;
    blobs.push(file.setName(path+n));
  }
  names = {};
  var folders = rootFolder.getFolders();
  while (folders.hasNext()) {
    var folder = folders.next();
    var n = folder.getName();
    while(names[n]) { n = '_' + n }
    names[n] = true;
    var fPath = path+n+'/';
    blobs.push(Utilities.newBlob([]).setName(fPath)); //comment/uncomment this line to skip/include empty folders
    blobs = blobs.concat(getBlobs(folder, fPath));
  }
  return blobs;
}
于 2015-01-19T05:08:58.227 回答
2

我能够使用@Hafez 发布的代码,但我需要修改它,因为它不适合我。我添加了前三行,因为我需要文件夹 ID,它是一个字符串值,而不是文件夹的名称。

var folderName = DriveApp.getFoldersByName("<folderName>");
var theFolder = folderName.next();
var folderID =theFolder.getId();
var folder = DriveApp.getFolderById(folderID);
var zipped = Utilities.zip(getBlobs(folder, ''), folder.getName()+'.zip');
folder.getParents().next().createFile(zipped);

function getBlobs(rootFolder, path) {
  var blobs = [];
  var files = rootFolder.getFiles();
  while (files.hasNext()) {
    var file = files.next().getBlob();
    file.setName(path+file.getName());
    blobs.push(file);
  }
  var folders = rootFolder.getFolders();
  while (folders.hasNext()) {
    var folder = folders.next();
    var fPath = path+folder.getName()+'/';
    blobs.push(Utilities.newBlob([]).setName(fPath)); //comment/uncomment this line to skip/include empty folders
    blobs = blobs.concat(getBlobs(folder, fPath));
  }
  return blobs;
}

我遇到的唯一奇怪的事情是,当我运行脚本时它说TypeError: Cannot call method "getFiles" of undefined. (line 10, file "Code"). 当我碰巧看到这个脚本所在的地方时,还有 5 个完整的 zip 文件。它有效,但我仍然收到该错误。奇怪......但这段代码对我有用。感谢这个线程上的每个人。干杯!

于 2016-02-26T21:38:55.923 回答
1

确实没有 API 参考。您可以在 Apps Script issue tracker上打开有关此问题的问题请求。但是从代码完成显示的内容推断,这是我的理解:

var folder = DocsList.getFolder('path/to/folder');
var files = folder.getFiles();
var blobs = [];
for( var i in files )
  blobs.push(files[i].getBlob());
var zip = Utilities.zip(blobs, 'newFiles.zip');
folder.createFile(zip);

但是我没有测试过这段代码,所以我不知道它是否可以工作。此外,它可能仅适用于未转换为 Google 格式的文件,或者可能仅适用于这些文件或其中的一部分。好吧,如果您尝试一下并找到一些东西,请在此处与我们分享。您肯定会面临的一个限制是文件大小,如果 zip 文件变得“太大”,它可能无法正常工作......是的,您也必须测试这个限制。

于 2012-11-06T20:54:25.230 回答
0

如果 Hafez 解决方案没有成功,并且您收到此错误

TypeError:无法读取未定义的属性“getFiles”

尝试这样做

/**
 * Creates a zipFile of the mentioned document ID and store it in Drive. You can search the zip by folderName.zip
 */

function createAndSendDocument() {
    var files = DriveApp.getFolderById("DOCUMENT ID CAN BE FIND IN THE URL WHEN A DOCUMENT IS OPENED");
    var folder = files;
    var zipped = Utilities.zip(getBlobs(folder, ''), folder.getName() + '.zip');
    folder.getParents().next().createFile(zipped);

}

function getBlobs(rootFolder, path) {
    var blobs = [];
    var files = rootFolder.getFiles();

    while (files.hasNext()) {
        var file = files.next().getBlob();
        file.setName(path+file.getName());
        blobs.push(file);
    }

    var folders = rootFolder.getFolders();

    while (folders.hasNext()) {
        var folder = folders.next();
        var fPath = path+folder.getName() + '/';
        blobs.push(Utilities.newBlob([]).setName(fPath)); //comment/uncomment this line to skip/include empty folders
        blobs = blobs.concat(getBlobs(folder, fPath));
    }

    return blobs;
}
于 2021-05-28T21:32:39.040 回答