Создание zip файла на Google Диске с помощью скрипта Apps

У меня есть папка в папке Google Drive, содержащая несколько файлов. Я хочу создать скрипт Google Apps, который будет заархивировать все файлы в этой папке и создать zip файл в той же папке.

Я нашел видео с функцией Utilities.zip(), но нет ссылки на API для этого. Как мне это использовать? Заранее спасибо.

Ответ 1

На самом деле это еще проще. Файлы уже являются Blobs (все, что имеет getBlob(), могут быть переданы любой функции, ожидающей Blobs). Таким образом, код выглядит следующим образом:

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'));

Ответ 2

Поскольку 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 делает массив всех файлов в папке и изменяет каждое имя файла на относительный путь, чтобы сохранить структуру, когда она стала zipped.

Чтобы закрепить папку, содержащую несколько элементов с тем же именем, используйте эту функцию 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;
}

Ответ 3

Нет ссылки на API. Вы можете открыть запрос о проблемах по этому вопросу в приложении Script отслеживание проблем. Но, исходя из того, что показывает завершение кода, вот мое понимание:

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 файл станет "слишком большим"... да, вам также придется проверить этот предел.

Ответ 4

Мне удалось использовать код, который был опубликован @Hafez, но мне нужно было его изменить, потому что он не работал у меня. Я добавил первые три строки, потому что мне нужен идентификатор папки, который является строковым значением и не является именем папки.

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;
}

Единственное, что я испытываю, это то, что когда я запускаю script, он говорит TypeError: Cannot call method "getFiles" of undefined. (line 10, file "Code"). Когда мне довелось посмотреть на место, где проживает этот script, было также 5 завершенных файлов zip. Он работает, но я все еще получаю эту ошибку. Странно... но этот код работает для меня. Спасибо всем в этой теме. Ура!