Нужно ZIP весь каталог с помощью Node.js
Мне нужно застегнуть весь каталог с помощью Node.js. В настоящее время я использую node -zip, и каждый раз, когда процесс запускается, он генерирует недопустимый ZIP файл (как вы можете видеть из эту проблему Github).
Есть ли другой, более лучший вариант Node.js, который позволит мне ZIP-каталог?
EDIT: я закончил использование archiver
writeZip = function(dir,name) {
var zip = new JSZip(),
code = zip.folder(dir),
output = zip.generate(),
filename = ['jsd-',name,'.zip'].join('');
fs.writeFileSync(baseDir + filename, output);
console.log('creating ' + filename);
};
значение образца для параметров:
dir = /tmp/jsd-<randomstring>/
name = <randomstring>
UPDATE:. Для тех, кто спрашивает о реализации, которую я использовал, здесь ссылка на мой загрузчик:
Ответы
Ответ 1
В итоге я использовал archiver lib. Отлично работает.
Example
var file_system = require('fs');
var archiver = require('archiver');
var output = file_system.createWriteStream('target.zip');
var archive = archiver('zip');
output.on('close', function () {
console.log(archive.pointer() + ' total bytes');
console.log('archiver has been finalized and the output file descriptor has closed.');
});
archive.on('error', function(err){
throw err;
});
archive.pipe(output);
archive.bulk([
{ expand: true, cwd: 'source', src: ['**'], dest: 'source'}
]);
archive.finalize();
Ответ 2
Я не претендую на то, чтобы показывать что-то новое, просто хочу обобщить приведенные выше решения для тех, кто любит использовать функции Promise в своем коде (например, я).
const archiver = require('archiver');
/**
* @param {String} source
* @param {String} out
* @returns {Promise}
*/
function zipDirectory(source, out) {
const archive = archiver('zip', { zlib: { level: 9 }});
const stream = fs.createWriteStream(out);
return new Promise((resolve, reject) => {
archive
.directory(source, false)
.on('error', err => reject(err))
.pipe(stream)
;
stream.on('close', () => resolve());
archive.finalize();
});
}
Надеюсь, это кому-нибудь поможет;)
Ответ 3
Чтобы включить все файлы и каталоги:
archive.bulk([
{
expand: true,
cwd: "temp/freewheel-bvi-120",
src: ["**/*"],
dot: true
}
]);
Он использует node -glob (https://github.com/isaacs/node-glob), поэтому любое совместимое с ним выражение будет работать.
Ответ 4
Archive.bulk
теперь устарел, новый метод, который будет использоваться для этого, glob:
var fileName = 'zipOutput.zip'
var fileOutput = fs.createWriteStream(fileName);
fileOutput.on('close', function () {
console.log(archive.pointer() + ' total bytes');
console.log('archiver has been finalized and the output file descriptor has closed.');
});
archive.pipe(fileOutput);
archive.glob("../dist/**/*"); //some glob pattern here
archive.glob("../dist/.htaccess"); //another glob pattern
// add as many as you like
archive.on('error', function(err){
throw err;
});
archive.finalize();
Ответ 5
Это еще одна библиотека, которая упаковывает папку в одну строку:
зип-локальный
var zipper = require('zip-local');
zipper.sync.zip("./hello/world/").compress().save("pack.zip");
Ответ 6
Используйте Node native child_process
api для этого.
Нет необходимости в сторонних библиотеках. Две строки кода.
const child_process = require("child_process");
child_process.execSync('zip -r DESIRED_NAME_OF_ZIP_FILE_HERE *', {
cwd: PATH_TO_FOLDER_YOU_WANT_ZIPPED_HERE
});
Я использую синхронный API. Вы можете использовать child_process.exec(path, options, callback)
если вам нужна асинхронность. Существует намного больше возможностей, чем просто указание CWD для дальнейшей настройки ваших запросов. Смотрите exec/execSync документы.
Обратите внимание: в этом примере предполагается, что в вашей системе установлена утилита zip (по крайней мере, она поставляется с OSX). Некоторые операционные системы могут не иметь установленной утилиты (т.е. среда выполнения AWS Lambda не имеет). В этом случае вы можете легко получить здесь двоичный файл утилиты zip и упаковать его вместе с исходным кодом своего приложения (для AWS Lambda вы можете также упаковать его в Lambda Layer), или вам придется либо использовать сторонний модуль (которых много на NPM). Я предпочитаю первый подход, поскольку утилита ZIP испытывается и тестируется десятилетиями.
Ответ 7
У Adm-zip есть проблемы, просто сжимающие существующий архив https://github.com/cthackers/adm-zip/issues/64, а также повреждение с сжатием двоичных файлов.
Я также столкнулся с проблемами сжатия с node -zip https://github.com/daraosn/node-zip/issues/4
node -archiver - единственный, который, кажется, хорошо работает для сжатия, но у него нет никаких функций без сжатия.
Ответ 8
Чтобы передать результат в объект ответа (сценарии, в которых необходимо загружать zip, а не хранить локально)
archive.pipe(res);
Смытые подсказки для доступа к содержимому каталога работали для меня.
src: ["**/*"]
Ответ 9
Я нашел эту маленькую библиотеку, которая содержит то, что вам нужно.
npm install zip-a-folder
const zip-a-folder = require('zip-a-folder');
await zip-a-folder.zip('/path/to/the/folder', '/path/to/archive.zip');
https://www.npmjs.com/package/zip-a-folder
Ответ 10
Вы можете попробовать простым способом:
Установите zip-dir
:
npm install zip-dir
и использовать это
var zipdir = require('zip-dir');
let foldername = src_path.split('/').pop()
zipdir(<<src_path>>, { saveTo: 'demo.zip' }, function (err, buffer) {
});
Ответ 11
Поскольку archiver
долгое время не совместим с новой версией веб-пакета, я рекомендую использовать zip-lib.
var zl = require("zip-lib");
zl.archiveFolder("path/to/folder", "path/to/target.zip").then(function () {
console.log("done");
}, function (err) {
console.log(err);
});