Node.js 中的 Zip 压缩文件

49

我想在node.js中创建一个zip压缩文件并解压它。

我找不到任何node实现。


https://github.com/pquerna/node-archive - Emmerman
node-archive并不是非常友好的开发者工具,文档非常差,示例也没有涵盖实际创建ZIP文件,只能读取现有的ZIP文件。 - Eliseo Soto
不错的发现。我只需要读取一个zip文件,所以这应该没问题...希望如此。 - Oscar Godson
10个回答

30

node-core内置了压缩功能:http://nodejs.org/api/zlib.html

使用它们:

var zlib = require('zlib');
var gzip = zlib.createGzip();
var fs = require('fs');
var inp = fs.createReadStream('input.txt');
var out = fs.createWriteStream('input.txt.gz');

inp.pipe(gzip).pipe(out);

3
但这不是 .zip 格式。我希望他们真的能在核心中内置一个 .zip 归档模块。 - Daniel Cheung
使用zip相比gzip有什么优势? - dopatraman
6
基本上,gzip会将整个文件压缩,而zip会分别压缩每个文件。在不同的情况下,可以选择使用其中一个。 - aug
有没有异步的方式来做这件事? - Stephan Kristyn
我们能否使用这个内置模块压缩文件夹? - Muhammad Uzair

29

我最终是这样做的(我使用Express)。我正在创建一个包含给定目录(SCRIPTS_PATH)中所有文件的ZIP。

我只在Mac OS X Lion上测试过,但我猜在安装了Cygwin的Linux和Windows上也可以正常工作。

var spawn = require('child_process').spawn;
app.get('/scripts/archive', function(req, res) {
    // Options -r recursive -j ignore directory info - redirect to stdout
    var zip = spawn('zip', ['-rj', '-', SCRIPTS_PATH]);

    res.contentType('zip');

    // Keep writing stdout to res
    zip.stdout.on('data', function (data) {
        res.write(data);
    });

    zip.stderr.on('data', function (data) {
        // Uncomment to see the files being added
        // console.log('zip stderr: ' + data);
    });

    // End the response on zip exit
    zip.on('exit', function (code) {
        if(code !== 0) {
            res.statusCode = 500;
            console.log('zip process exited with code ' + code);
            res.end();
        } else {
            res.end();
        }
    });
});

2
确认这在Linux上没有问题,使用安装了zip的Node 0.4.9版本。感谢Eliseo提供的代码,肯定节省了我不少时间。 - Eliot Sykes
1
有人能确认这个程序在Windows上不需要Cygwin就可以运行吗? - Ash Blue
谢谢你的建议。只有一个问题 - 我如何设置浏览器下载存档的名称?尝试设置内容-下载头文件,但这并没有帮助。 - ecdeveloper
“app”变量是什么?那是一个http进程吗? - commadelimited
"app" 是使用 Express JS 创建的 HTTP 应用程序。 - Eliseo Soto
这个答案正在挑战我所谓的“在node.js中”的范畴,它只有在你安装了这些特定的二进制文件时才能工作。就我个人而言,我正在寻找一个可以处理此工作而不生成子进程的node.js库。 - Stephen Crosby

10
您可以尝试使用node-zip npm模块。
它将JSZip移植到了Node.js中,用来压缩/解压缩zip文件。

既然你看起来是作者:你的模块的目的是什么?就我所看到的,它只是JsZip的包装器:`var fs = require('fs'); var JSZip = require('jszip');global.JSZip = JSZip; module.exports = function(data, options) { return new JSZip(data, options) };` 我在使用JsZip时遇到了问题,因为它不是异步的,你的模块解决了这个问题吗? - Eugene
从问题跟踪器https://github.com/daraosn/node-zip/issues/12: "这个项目已经超过2年了,在那个时候我不能直接在node应用程序上使用JSZip,就像我在前端应用程序上做的那样。 node-zip只是包装了一个全局JSZip变量,以便直接在应用程序中使用,并包括一个CLI。所以,是的,它只是一个端口,我正在维护它以保留遗留原因,因为许多项目正在使用它。随意直接使用JSZip。" - adabru

7
您可以使用archiver模块,这对我非常有帮助。以下是一个示例:
var Archiver = require('archiver'),
    fs = require('fs');
app.get('download-zip-file', function(req, res){    
    var archive = Archiver('zip');
    archive.on('error', function(err) {
        res.status(500).send({error: err.message});
    });
    //on stream closed we can end the request
    res.on('close', function() {
        console.log('Archive wrote %d bytes', archive.pointer());
        return res.status(200).send('OK').end();
    });
    //set the archive name
    res.attachment('file-txt.zip');
    //this is the streaming magic
    archive.pipe(res);
    archive.append(fs.createReadStream('mydir/file.txt'), {name:'file.txt'});
    //you can add a directory using directory function
    //archive.directory(dirPath, false);
    archive.finalize();
});

1

我发现自己编写7-zip的包装器最容易,但您也可以轻松地使用zip或任何命令行zip工具,只要在运行时环境中可用。这个特定的模块只做一件事:压缩一个目录。

const { spawn } = require('child_process');
const path = require('path');

module.exports = (directory, zipfile, log) => {
  return new Promise((resolve, reject) => {
    if (!log) log = console;

    try {
      const zipArgs = ['a', zipfile, path.join(directory, '*')];
      log.info('zip args', zipArgs);
      const zipProcess = spawn('7z', zipArgs);
      zipProcess.stdout.on('data', message => {
        // received a message sent from the 7z process
        log.info(message.toString());
      });

      // end the input stream and allow the process to exit
      zipProcess.on('error', (err) => {
        log.error('err contains: ' + err);
        throw err;
      });

      zipProcess.on('close', (code) => {
        log.info('The 7z exit code was: ' + code);
        if (code != 0) throw '7zip exited with an error'; // throw and let the handler below log it
        else {
          log.info('7zip complete');
          return resolve();
        }
      });
    }
    catch(err) {
      return reject(err);
    }
  });
}

假设您已将上述代码保存到zipdir.js中,请像这样使用它。第三个log参数是可选的。如果您有自定义日志记录器,请使用它。或者完全删除我讨厌的日志语句。

const zipdir = require('./zipdir');

(async () => {
  await zipdir('/path/to/my/directory', '/path/to/file.zip');
})();

1

adm-zip

这是一个仅使用JavaScript的库,用于在内存中读取、创建和修改zip压缩文件。

它看起来很不错,但有一些小问题。我在解压文本文件时遇到了一些麻烦。


2
对我来说,它似乎也有漏洞,在使用7zip压缩和检查大文件时出现crc错误。 - JohnC
2
这个软件包存在不负责任的依赖版本控制,目前正在引起混乱。请勿使用它。 - lazd
1
@lazd所做的评论现已得到纠正,adm-zip不再造成混乱... - holroy
2
@holroy,没错,他们移除了有问题的模块,现在一切都好了。 - lazd
adm-zip仍然存在问题,因为它使用的压缩方式会创建有问题的zip归档文件。请参阅此github问题:https://github.com/cthackers/adm-zip/issues/102 - smb
显示剩余2条评论

1

1
如果你只需要解压缩,node-zipfile 看起来比 node-archive 更轻量级。它肯定有更小的学习曲线。

0

-4

1
这并没有回答问题。使用库来运行.NET代码以执行解压缩,如何是一个节点实现? - Jonathan Dumaine
3
你不觉得包含整个.NET框架,并在进程中进行托管,仅仅为了压缩和解压文件而增加了很多复杂性吗? - MateodelNorte
请看下面我的回复,了解如何使用node-core内置模块来压缩文件。 - MateodelNorte

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接