需要使用 Node.js 压缩整个目录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15641243/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Need to ZIP an entire directory using Node.js
提问by commadelimited
I need to zip an entire directory using Node.js. I'm currently using node-zip and each time the process runs it generates an invalid ZIP file (as you can see from this Github issue).
我需要使用 Node.js 压缩整个目录。我目前正在使用 node-zip 并且每次进程运行时它都会生成一个无效的 ZIP 文件(正如您从这个 Github issue 中看到的那样)。
Is there another, better, Node.js option that will allow me to ZIP up a directory?
是否有另一个更好的 Node.js 选项可以让我压缩目录?
EDIT: I ended up using 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);
};
sample value for parameters:
参数的样本值:
dir = /tmp/jsd-<randomstring>/
name = <randomstring>
UPDATE:For those asking about the implementation I used, here's a link to my downloader:
更新:对于那些询问我使用的实现的人,这里是我的下载器的链接:
回答by commadelimited
I ended up using archiverlib. Works great.
我最终使用了归档程序库。效果很好。
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();
回答by D.Dimitrioglo
I do not pretend to show something new, just want to summarize solutions above for those who likes to use Promise functions in their code (like me).
我不假装展示什么新东西,只是想为那些喜欢在他们的代码中使用 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();
});
}
Hope it will help someone ;)
希望它会帮助某人;)
回答by caiocpricci2
Archive.bulkis now deprecated, the new method to be used for this is glob:
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();
回答by Govind Rai
Use Node's native child_processapi to accomplish this.
使用 Node 的本机child_processapi 来完成此操作。
No need for third party libs. Two lines of code.
不需要第三方库。两行代码。
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
});
I'm using the synchronous API. You can use child_process.exec(path, options, callback)if you need async. There are a lot more options than just specifying the CWD to further finetune your requests. See exec/execSyncdocs.
我正在使用同步 API。child_process.exec(path, options, callback)如果需要异步,可以使用。除了指定 CWD 以进一步微调您的请求之外,还有更多选项。请参阅exec/execSync文档。
Please note:This example assumes you have the zip utility installed on your system (it comes with OSX, at least). Some operating systems may not have utility installed (i.e., AWS Lambda runtime doesn't). In that case, you can easily obtain the zip utility binary hereand package it along with your application source code (for AWS Lambda you can package it in a Lambda Layer as well), or you'll have to either use a third party module (of which there are plenty on NPM). I prefer the former approach, as the ZIP utility is tried and tested for decades.
请注意:此示例假设您的系统上安装了 zip 实用程序(它至少随 OSX 一起提供)。某些操作系统可能未安装实用程序(即,AWS Lambda 运行时未安装)。在这种情况下,您可以在此处轻松获取 zip 实用程序二进制文件并将其与应用程序源代码一起打包(对于 AWS Lambda,您也可以将其打包在 Lambda 层中),或者您必须使用第三方模块(其中在 NPM 上有很多)。我更喜欢前一种方法,因为 ZIP 实用程序已经经过了数十年的尝试和测试。
回答by Sam Ghaderyan
To include all files and directories:
要包含所有文件和目录:
archive.bulk([
{
expand: true,
cwd: "temp/freewheel-bvi-120",
src: ["**/*"],
dot: true
}
]);
It uses node-glob(https://github.com/isaacs/node-glob) underneath, so any matching expression compatible with that will work.
它在下面使用 node-glob( https://github.com/isaacs/node-glob),因此任何与之兼容的匹配表达式都可以使用。
回答by Dreams
回答by Raf
To pipe the result to the response object (scenarios where there is a need to download the zip rather than store locally)
将结果通过管道传送到响应对象(需要下载 zip 而不是本地存储的场景)
archive.pipe(res);
Sam's hints for accessing the content of the directory worked for me.
Sam 访问目录内容的提示对我有用。
src: ["**/*"]
回答by Xiaoxin
Adm-zip has problems just compressing an existing archive https://github.com/cthackers/adm-zip/issues/64as well as corruption with compressing binary files.
Adm-zip 仅在压缩现有存档https://github.com/cthackers/adm-zip/issues/64 时就会出现问题,并且在压缩二进制文件时会出现损坏。
I've also ran into compression corruption issues with node-zip https://github.com/daraosn/node-zip/issues/4
我还遇到了 node-zip 压缩损坏问题https://github.com/daraosn/node-zip/issues/4
node-archiver is the only one that seems to work well to compress but it doesn't have any uncompress functionality.
node-archiver 是唯一一种似乎可以很好地压缩但它没有任何解压缩功能的工具。
回答by Ondrej Kvasnovsky
I have found this small library that encapsulates what you need.
我找到了这个小型库,可以封装您需要的内容。
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');
回答by tao
Since archiveris not compatible with the new version of webpack for a long time, I recommend using zip-lib.
由于archiver长时间不兼容新版webpack,推荐使用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);
});

