需要使用Node.js压缩整个目录

时间:2013-03-26 15:41:32

标签: node.js zip

我需要使用Node.js压缩整个目录。我目前正在使用node-zip,每次进程运行时都会生成一个无效的ZIP文件(正如您从this Github issue看到的那样)。

是否有另一个更好的Node.js选项可以让我压缩目录?

编辑:我最终使用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>

更新:对于那些询问我使用的实施的人,here's a link to my downloader

12 个答案:

答案 0 :(得分:94)

我最终使用了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();

答案 1 :(得分:17)

我不假装展示一些新东西,只是想为那些喜欢在其代码中使用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();
  });
}

希望它将对某人有所帮助;)

答案 2 :(得分:10)

包含所有文件和目录:

archive.bulk([
  {
    expand: true,
    cwd: "temp/freewheel-bvi-120",
    src: ["**/*"],
    dot: true
  }
]);

它在下面使用了node-glob(https://github.com/isaacs/node-glob),因此任何与之兼容的匹配表达式都可以。

答案 3 :(得分:9)

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

答案 4 :(得分:4)

使用Node的本地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实用程序二进制here并将其与应用程序源代码一起打包(对于AWS Lambda,您也可以将其打包在Lambda层中),或者您必须要么使用第三方模块(NPM上有很多)。 我更喜欢前一种方法,因为ZIP实用程序已经过几十年的尝试和测试。

答案 5 :(得分:3)

Adm-zip只是压缩现有存档https://github.com/cthackers/adm-zip/issues/64以及压缩二进制文件时出现问题。

我还遇到了node-zip https://github.com/daraosn/node-zip/issues/4

的压缩损坏问题

node-archiver是唯一一个似乎能够很好地进行压缩但它没有任何解压缩功能的节点。

答案 6 :(得分:3)

将结果传递给响应对象(需要下载zip而不是本地存储的场景)

 archive.pipe(res);

Sam提示访问为我工作的目录内容。

src: ["**/*"]

答案 7 :(得分:2)

这是另一个将文件夹压缩为一行的库: zip-local

var zipper = require('zip-local');

zipper.sync.zip("./hello/world/").compress().save("pack.zip");

答案 8 :(得分:0)

我发现了这个小型库,其中包含您所需的内容。

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

答案 9 :(得分:0)

您可以通过一种简单的方式尝试:

安装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) {

    });

答案 10 :(得分:0)

由于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);
});

答案 11 :(得分:0)

我最终包装了存档器来模拟JSZip,因为通过我的项目进行重构将花费很多精力。我了解Archiver可能不是最佳选择,但是您可以选择这里。

// USAGE:
const zip=JSZipStream.to(myFileLocation)
    .onDone(()=>{})
    .onError(()=>{});

zip.file('something.txt','My content');
zip.folder('myfolder').file('something-inFolder.txt','My content');
zip.finalize();

// NodeJS file content:
    var fs = require('fs');
    var path = require('path');
    var archiver = require('archiver');

  function zipper(archive, settings) {
    return {
        output: null,
        streamToFile(dir) {
            const output = fs.createWriteStream(dir);
            this.output = output;
            archive.pipe(output);

            return this;
        },
        file(location, content) {
            if (settings.location) {
                location = path.join(settings.location, location);
            }
            archive.append(content, { name: location });
            return this;
        },
        folder(location) {
            if (settings.location) {
                location = path.join(settings.location, location);
            }
            return zipper(archive, { location: location });
        },
        finalize() {
            archive.finalize();
            return this;
        },
        onDone(method) {
            this.output.on('close', method);
            return this;
        },
        onError(method) {
            this.output.on('error', method);
            return this;
        }
    };
}

exports.JSzipStream = {
    to(destination) {
        console.log('stream to',destination)
        const archive = archiver('zip', {
            zlib: { level: 9 } // Sets the compression level.
        });
        return zipper(archive, {}).streamToFile(destination);
    }
};