Archiver — Streaming Archive Packaging

基于 Node.js 的流式压缩库,支持 ZIP/TAR 格式创建与多源数据打包。

已扫描
适合谁
Node.js 开发者、后端自动化工程师
不适合谁
无编程基础的普通用户、无需文件压缩功能的非技术用户
国内可用性
需网络配置。可能需要网络配置或第三方服务可访问。
安装难度
新手友好(★☆☆)。基于终端操作、依赖、API Key 和本地环境要求的初步判断。

安装与下载

openclaw skills install @openlark/archiver

Skill 说明

命令、参数、文件名以原文为准

Archiver — 流式归档打包

一个基于 Node.js 的流式归档库,支持 ZIP 和 TAR 格式,可从多个数据源追加内容。

使用场景

适用于用户需要压缩和打包、创建 zip/tar 归档文件、打包目录或程序化生成压缩文件的场景。

触发关键词

压缩、打包、归档、zip、tar、archive、archiver

安装

npm install archiver

快速入门:ZIP 打包

const fs = require('fs');
const archiver = require('archiver');

const output = fs.createWriteStream('output.zip');
const archive = archiver('zip', { zlib: { level: 9 } });

output.on('close', () => {
  console.log(`${archive.pointer()} 字节已写入`);
});

archive.on('error', (err) => { throw err; });

archive.pipe(output);

// 追加 — 多个数据源
archive.append(fs.createReadStream('file.txt'), { name: 'file.txt' });  // 流
archive.append('字符串内容', { name: 'readme.txt' });                     // 字符串
archive.append(Buffer.from('数据'), { name: 'data.bin' });               // 缓冲区
archive.file('本地文件.txt', { name: '重命名.txt' });                    // 本地文件路径
archive.directory('src/', 'src');                                        // 目录 → 归档中的子目录
archive.directory('dist/', false);                                       // 目录内容 → 归档根目录
archive.glob('*.js', { cwd: __dirname });                                // glob 匹配

archive.finalize();

数据源概览

方法数据源name 参数说明
archive.append(stream, { name })可读流(ReadStream)必填
archive.append(string, { name })字符串必填
archive.append(buffer, { name })缓冲区(Buffer)必填
archive.file(path, { name })文件路径可选,可用于重命名
archive.directory(path, dest)目录false 表示内容放入根目录;字符串表示作为子目录名
archive.glob(pattern, { cwd })glob 匹配自动使用匹配的文件名

TAR 打包

const archive = archiver('tar', {
  gzip: true,
  gzipOptions: { level: 6 }
});

TAR 特有选项:

选项描述默认值
gzip启用 gzip 压缩false
gzipOptions.level压缩级别 0-96

事件

archive.on('warning', (err) => {
  if (err.code === 'ENOENT') console.warn('文件未找到:', err);
  else throw err;
});

archive.on('error', (err) => { throw err; });

// 来自 Node.js Stream API 的管道目标流事件
output.on('close', () => { /* 文件描述符已关闭 */ });
output.on('end', () => { /* 数据已耗尽 */ });
output.on('finish', () => { /* 所有数据已写入 */ });
  • **warning** — 非致命错误(如文件未找到、stat 失败等);ENOENT 可忽略,其他应抛出异常
  • **error** — 致命错误;必须处理
  • **close**(输出流)— 文件描述符关闭后触发;此时可使用 archive.pointer() 获取总字节数
  • **end**(输出流)— 数据已耗尽;无论数据源如何都会触发
  • **progress** — 进度追踪,详见下文

进度追踪

archive.on('progress', (progress) => {
  console.log(`${progress.entries.processed} / ${progress.entries.total} 项`);
  console.log(`${progress.fs.processedBytes} / ${progress.fs.totalBytes} 字节`);
});

progress 对象结构:

{
  entries: { total: number, processed: number },
  fs: { totalBytes: number, processedBytes: number }
}

常见模式

模式 1:响应式归档 — HTTP 流式输出

app.get('/download', (req, res) => {
  res.attachment('archive.zip');
  const archive = archiver('zip', { zlib: { level: 1 } }); // 低压缩等级 = 更快

  archive.on('error', (err) => { res.status(500).end(); });

  archive.pipe(res);
  archive.directory('user-files/', false);
  archive.finalize();
});

模式 2:条件追加 — 按需打包

const archive = archiver('zip');

// 根据条件动态追加
if (includeSource) {
  archive.directory('src/', 'source');
}
if (includeDocs) {
  archive.glob('docs/**/*.md', { cwd: __dirname });
}

archive.finalize();

模式 3:内存中归档 — 无文件输出

const { Writable } = require('stream');

const chunks = [];
const memoryStream = new Writable({
  write(chunk, enc, cb) { chunks.push(chunk); cb(); }
});

const archive = archiver('zip');
archive.pipe(memoryStream);

archive.append('hello', { name: 'hello.txt' });
archive.finalize();

memoryStream.on('finish', () => {
  const buffer = Buffer.concat(chunks);
  console.log(`内存中的归档大小: ${buffer.length} 字节`);
  // 可用于上传、发送等操作
});

模式 4:批量打包 — 依次生成多个归档

async function createBatchedArchives(fileGroups, outputDir) {
  for (const [i, files] of fileGroups.entries()) {
    await new Promise((resolve, reject) => {
      const output = fs.createWriteStream(`${outputDir}/batch-${i}.zip`);
      const archive = archiver('zip');

      archive.on('error', reject);
      output.on('close', resolve);

      archive.pipe(output);
      files.forEach(f => archive.file(f, { name: path.basename(f) }));
      archive.finalize();
    });
    console.log(`批次 ${i} 完成`);
  }
}

自定义格式注册

archiver.registerFormat('myformat', module);
const archive = archiver('myformat');

检查格式是否已注册:

if (archiver.isRegisteredFormat('zip')) {
  // ZIP 已可用
}

符号链接处理

archive.symlink('目标路径', { name: '链接名称' });

常用选项参考 — archiver(format, options)

const archive = archiver('zip', {
  zlib: { level: 9 },          // 压缩级别 0-9
  comment: 'my comment',       // ZIP 注释
  forceLocalTime: true,        // 使用本地时间而非 UTC
  forceZip64: false,           // 是否强制使用 Zip64 格式
  namePrependSlash: false,     // 文件名前不添加斜杠 /
  statConcurrency: 4           // 并发 stat 操作数量
});

有关完整的 API 参考,请参阅 [references/api-reference.md](references/api-reference.md)。

O
@openlark

已收录 9 个 Skill

相关推荐