这些库用于在 JavaScript 环境中创建和解压 ZIP 文件。adm-zip 和 archiver 主要用于 Node.js 服务端,jszip 专注于浏览器和同构场景,而 node-zip 和 zip-local 已过时。选择取决于运行环境(Node 还是浏览器)、文件大小(流式还是内存)以及 API 偏好(同步还是异步)。
在 JavaScript 生态中处理 ZIP 文件是一个常见需求,无论是前端下载打包资源,还是后端生成报表归档。adm-zip、archiver、jszip 是目前的三大主流选择,而 node-zip、zip-local 等旧库已逐渐退出历史舞台。本文将从架构设计、运行环境、API 风格三个维度进行深度对比。
不同的库采用了不同的数据处理模型,这直接决定了它们的性能表现和适用场景。
adm-zip 采用 同步内存操作。
// adm-zip: 同步写入
const AdmZip = require('adm-zip');
const zip = new AdmZip();
zip.addLocalFolder('./data');
zip.writeZip('./output.zip'); // 阻塞直到完成
archiver 采用 流式处理(Streaming)。
// archiver: 流式管道
const archiver = require('archiver');
const output = fs.createWriteStream('./output.zip');
const archive = archiver('zip');
archive.pipe(output);
archive.directory('./data', false);
archive.finalize(); // 非阻塞
jszip 采用 Promise 异步操作。
// jszip: Promise 异步
const JSZip = require('jszip');
const zip = new JSZip();
zip.file('hello.txt', 'Hello World');
zip.generateAsync({ type: 'blob' }).then(content => {
// 保存或下载 blob
});
node-zip 采用 回调风格(已弃用)。
// node-zip: 遗留回调风格
const zip = require('node-zip');
const data = zip('file.txt', 'content');
// 缺乏现代异步支持
zip-a-folder 采用 封装式异步。n- 基于 archiver 封装,简化了文件夹压缩。
// zip-a-folder: 封装 Promise
const zipFolder = require('zip-a-folder');
await zipFolder.zip('./data', './output.zip');
zip-local 采用 同步/异步混合(已弃用)。
// zip-local: 遗留 API
const zip = require('zip-local');
zip.sync.zip('./data').compress().save('./output.zip');
环境兼容性是选型的第一道门槛。
adm-zip:仅支持 Node.js。依赖文件系统模块(fs),无法在浏览器运行。archiver:仅支持 Node.js。依赖流(stream)和文件系统,专为服务端设计。jszip:支持 Node.js 和 浏览器。纯 JavaScript 实现,无系统依赖,是同构首选。node-zip:仅支持 Node.js(旧版本)。zip-a-folder:仅支持 Node.js。zip-local:仅支持 Node.js。💡 提示:如果你的项目需要在 Web Worker 或前端直接打包文件,
jszip是唯一可靠的选择。
在选择库时,维护状态直接关系到安全性和 Bug 修复速度。
| 包名 | 状态 | 建议 |
|---|---|---|
adm-zip | ✅ 活跃维护 | 适合 Node 同步场景 |
archiver | ✅ 活跃维护 | 适合 Node 流式场景 |
jszip | ✅ 活跃维护 | 适合浏览器/同构 |
node-zip | ❌ 已弃用 | 不要使用 |
zip-local | ❌ 已弃用 | 不要使用 |
zip-a-folder | ⚠️ 有限维护 | 适合简单脚本 |
对于 node-zip 和 zip-local,npm 页面已标记为 deprecated 或长期未更新。在生产环境中使用它们可能会遇到 Node.js 新版本兼容性问题,甚至安全漏洞。
archiver// 使用 archiver 管道传输到 S3 或本地
archive.pipe(s3UploadStream);
jszip// 前端直接生成
zip.generateAsync({ type: 'blob' }).then(saveAs);
adm-zip 或 zip-a-folder// 简单一行代码
await zipFolder.zip('./src', './dist.zip');
node-zip 或 zip-localarchiver 或 jszip。| 特性 | adm-zip | archiver | jszip | node-zip | zip-a-folder | zip-local |
|---|---|---|---|---|---|---|
| 环境 | Node | Node | Node + 浏览器 | Node | Node | Node |
| 模式 | 同步 | 流式 | Promise | 回调 | Promise | 混合 |
| 大文件 | ❌ 内存风险 | ✅ 优秀 | ⚠️ 内存风险 | ❌ 差 | ⚠️ 依赖 archiver | ❌ 差 |
| 维护状态 | ✅ 活跃 | ✅ 活跃 | ✅ 活跃 | ❌ 弃用 | ⚠️ 一般 | ❌ 弃用 |
| 复杂度 | 低 | 中 | 中 | 低 | 极低 | 低 |
adm-zip 是 Node.js 同步操作的瑞士军刀 🇨🇭——简单直接,适合小文件脚本。
archiver 是服务端大数据处理的管道工 🚰——稳定高效,适合生产级后端服务。
jszip 是前后端通用的桥梁 🌉——灵活兼容,适合 Web 应用和同构项目。
node-zip 和 zip-local 是历史遗留物 🕸️——请避免在新项目中使用,老项目应尽快迁移。
zip-a-folder 是快速原型工具 🛠️——适合临时脚本,但核心业务建议直接用 archiver。
核心原则:优先考虑运行环境(浏览器选 jszip,服务端大文件选 archiver),其次考虑 API 风格(同步选 adm-zip)。避免使用已弃用的库以确保长期稳定性。
选择 adm-zip 如果你需要在 Node.js 环境中进行简单的同步 ZIP 操作,且文件大小适中。它的 API 直观,不需要处理流或 Promise,适合脚本工具或小型后端服务。
选择 archiver 如果你需要在 Node.js 服务端处理大文件或流式传输。它支持管道(pipe)操作,内存占用低,适合生成大型下载文件或备份系统。
选择 jszip 如果你的代码需要运行在浏览器中,或者需要基于 Promise 的异步 API。它对前端友好,支持读取 Blob 和 File 对象,适合网页内的文件打包功能。
不要在新项目中使用 node-zip。该库已弃用且多年未维护,存在兼容性问题。建议迁移到 jszip 或 archiver 以获得更好的支持和安全性。
选择 zip-a-folder 如果你只需要快速压缩整个文件夹且不想编写样板代码。它是 archiver 的封装,适合简单的 CLI 工具,但复杂场景建议直接用 archiver。
不要在新项目中使用 zip-local。该库已弃用,功能有限且不再维护。使用 adm-zip 或 archiver 替代可以获得更稳定的性能和社区支持。
ADM-ZIP is a pure JavaScript implementation for zip data compression for NodeJS.
With npm do:
$ npm install adm-zip
Electron file system support described below.
The library allows you to:
There are no other nodeJS libraries that ADM-ZIP is dependent of
var AdmZip = require("adm-zip");
// reading archives
var zip = new AdmZip("./my_file.zip");
var password = "1234567890";
var zipEntries = zip.getEntries(); // an array of ZipEntry records - add password parameter if entries are password protected
zipEntries.forEach(function (zipEntry) {
console.log(zipEntry.toString()); // outputs zip entries information
if (zipEntry.entryName == "my_file.txt") {
console.log(zipEntry.getData().toString("utf8"));
}
});
// outputs the content of some_folder/my_file.txt
console.log(zip.readAsText("some_folder/my_file.txt"));
// extracts the specified file to the specified location
zip.extractEntryTo(/*entry name*/ "some_folder/my_file.txt", /*target path*/ "/home/me/tempfolder", /*maintainEntryPath*/ false, /*overwrite*/ true);
// extracts everything
zip.extractAllTo(/*target path*/ "/home/me/zipcontent/", /*overwrite*/ true);
// creating archives
var zip = new AdmZip();
// add file directly
var content = "inner content of the file";
zip.addFile("test.txt", Buffer.from(content, "utf8"), "entry comment goes here");
// add local file
zip.addLocalFile("/home/me/some_picture.png");
// get everything as a buffer
var willSendthis = zip.toBuffer();
// or write everything to disk
zip.writeZip(/*target file name*/ "/home/me/files.zip");
// ... more examples in the wiki
For more detailed information please check out the wiki.
ADM-ZIP has supported electron original-fs for years without any user interractions but it causes problem with bundlers like rollup etc. For continuing support original-fs or any other custom file system module. There is possible specify your module by fs option in ADM-ZIP constructor.
Example:
const AdmZip = require("adm-zip");
const OriginalFs = require("original-fs");
// reading archives
const zip = new AdmZip("./my_file.zip", { fs: OriginalFs });
.
.
.