npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

unzip-plugin

v1.0.0

Published

开箱即用的 ZIP 解压插件。内置 @zip.js/zip.js,支持超大文件、密码解密、流式解压、进度反馈、暂停/恢复/取消与内存管理。可用于浏览器直解 ESModule / UMD,亦提供 Vue3 Composition API 封装。

Readme

unzip-plugin

开箱即用的 ZIP 解压插件,基于 @zip.js/zip.js 实现。

超大文件流式解压 · 密码解密(ZIP 2.0 / AES)· 进度反馈 · 暂停 / 恢复 / 取消 · 内存管理

内置 zip 解压引擎,安装即用、无需 CDN。提供与框架无关的核心类 ZipUncompressor(可在原生 JS、Node 或任意框架中使用),并提供 Vue3 Composition API 封装。


目录


1. 安装

npm install unzip-plugin
# 或
yarn add unzip-plugin

说明:底层 @zip.js/zip.js 已随插件打包进 dist,无需额外安装,也不依赖 CDN。


2. 引入(快速开始)

2.1 Vue3 全局注册(推荐)

// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import ZipPlugin from 'unzip-plugin'

createApp(App).use(ZipPlugin, {
  defaultOptions: { password: 'your-password' },
}).mount('#app')

注册后可通过全局属性 this.$zip(或 this.$zipUncompress)创建解压器实例:

// 任意组件内
const zip = this.$zip.create({ defaultOptions: { maxConcurrency: 4 } })
await zip.extractAll(file)

2.2 局部使用 Composable

import { useZipUncompress } from 'unzip-plugin'

const { extractAll, parse, progress, status, error } = useZipUncompress()

const handleFile = async (file: File) => {
  const result = await extractAll(file, { onProgress: (p) => console.log(p.percent) })
  console.log(result.files)
}

2.3 原生 JS / 非 Vue 使用核心类

核心类 ZipUncompressor 与框架无关,不依赖 Vue,可直接在原生 JS 或任意框架中使用:

import { ZipUncompressor } from 'unzip-plugin'

const uncompressor = new ZipUncompressor({
  onProgress: (p) => console.log(`进度: ${p.percent}%`),
})

const result = await uncompressor.extractAll(zipFile)

仓库内的 demo/ 目录即为一个基于 Vue3 + 原生 CSS 的完整示例,采用单文件组件并按标签页组织,完整覆盖 src/ 下全部 API(核心类 ZipUncompressor、useZipUncompress、ZipPlugin 全局 $zip、MemoryManager 及所有 UnzipOptions 配置项),未引入任何第三方 UI 框架。运行 npm run demo:dev 即可预览。


3. API 文档

3.1 核心类 ZipUncompressor

供非 Vue / 原生 JS 使用。所有方法均以 Blob | ArrayBuffer | File | Response 作为输入源。

| 方法 | 类型 | 说明 | | --- | --- | --- | | parse | (source) => Promise<ZipEntry[]> | 解析 ZIP 结构,获取文件列表 | | hasEncryptedFiles | (source) => Promise<boolean> | 是否包含加密文件 | | validatePassword | (source, password) => Promise<PasswordValidationResult> | 验证密码 | | extractAll | (source, options?) => Promise<UnzipResult> | 解压全部文件 | | extractFiles | (source, paths, options?) => Promise<UnzipResult> | 解压指定路径文件 | | extractStreaming | (source, options?) => AsyncGenerator<UnzipFile> | 流式逐个产出文件 | | pause | () => void | 暂停 | | resume | () => void | 恢复 | | cancel | () => void | 取消 | | reset | () => void | 重置状态 |

3.2 Composable useZipUncompress

| 参数名 | 类型 | 必填 | 默认值 | 说明 | | --- | --- | --- | --- | --- | | defaultOptions | Partial<UnzipOptions> | 否 | {} | 默认解压配置 | | callbacks | UnzipCallbacks | 否 | {} | 全局回调(onProgress / onError / onComplete) |

3.3 配置参数 UnzipOptions

| 参数名 | 类型 | 必填 | 默认值 | 说明 | 使用场景 | | --- | --- | --- | --- | --- | --- | | password | string | 否 | '' | 解压密码 | 加密 ZIP 文件 | | memoryThreshold | number | 否 | 536870912 | 内存阈值(字节):批量解压(extractAll/extractFiles)预估解压总大小超过时抛出 OUT_OF_MEMORY | 批量解压内存保护,默认 512MB | | maxConcurrency | number | 否 | 3 | 最大并发解压数(extractAll/extractFiles 生效;extractStreaming 为顺序流式输出) | 批量解压加速 | | filterPaths | string[] | 否 | [] | 仅解压命中的路径:支持完整路径、目录前缀或关键字子串;为空则解压全部 | 选择性解压 | | skipEncrypted | boolean | 否 | false | 跳过加密文件 | 不解压加密文件 | | onProgress | (progress: UnzipProgress) => void | 否 | - | 解压进度回调(按解压字节数回报) | 显示进度条 |

3.4 回调 UnzipCallbacks

| 回调名 | 类型 | 说明 | 使用场景 | | --- | --- | --- | --- | | onProgress | (progress: UnzipProgress) => void | 进度回调 | 进度条 | | onError | (error: UnzipError) => void | 错误回调 | 错误提示 | | onComplete | (result: UnzipResult) => void | 完成回调 | 解压后处理 |

3.5 返回值

useZipUncompress 返回:

| 属性 / 方法 | 类型 | 说明 | | --- | --- | --- | | status | Ref<UnzipStatus> | 解压状态 | | progress | Ref<UnzipProgress> | 解压进度 | | error | Ref<UnzipError \| null> | 错误信息 | | result | Ref<UnzipResult \| null> | 解压结果 | | entries | Ref<ZipEntry[]> | 解析后的文件条目 | | isLoading | Ref<boolean> | 是否加载中 | | isPaused | Ref<boolean> | 是否暂停 | | canResume | Ref<boolean> | 是否可以恢复 | | parse | (source) => Promise<ZipEntry[]> | 解析 | | hasEncryptedFiles | (source) => Promise<boolean> | 检测加密 | | validatePassword | (source, password) => Promise<PasswordValidationResult> | 验证密码 | | extractAll | (source, options?) => Promise<UnzipResult> | 解压全部 | | extractFiles | (source, paths, options?) => Promise<UnzipResult> | 解压选中 | | extractStreaming | (source, options?) => AsyncGenerator<UnzipFile> | 流式解压 | | pause / resume / cancel / reset | () => void | 控制方法 |

3.6 类型定义

type ZipSource = File | Blob | ArrayBuffer | Response;

interface ZipEntry {
  name: string;             // 文件名
  path: string;             // 文件路径
  uncompressedSize: number; // 解压后大小
  compressedSize: number;   // 压缩后大小
  compressionMethod: number;// 压缩方法
  isEncrypted: boolean;     // 是否加密
  encryptionMethod: EncryptionMethod; // 加密算法
  lastModified: Date;       // 最后修改时间
  crc32: number;            // CRC32 校验
  isDirectory: boolean;     // 是否目录
}

interface UnzipFile {
  name: string;             // 文件名
  path: string;             // 文件路径
  content: Blob | ArrayBuffer; // 文件内容
  size: number;             // 文件大小
  type: string;             // MIME 类型
  isEncrypted: boolean;
  lastModified: Date;
  extractTime: number;      // 解压耗时
}

interface UnzipResult {
  success: boolean;
  files: UnzipFile[];
  skippedFiles?: string[];  // 跳过的加密文件
  totalTime: number;        // 总耗时(ms)
  totalBytes: number;       // 总字节数
}

enum UnzipStatus { IDLE | LOADING | PARSING | DECRYPTING | EXTRACTING | SUCCESS | ERROR | PAUSED }

enum UnzipErrorCode {
  WRONG_PASSWORD | FILE_TOO_LARGE | UNSUPPORTED_ENCRYPT | OUT_OF_MEMORY |
  INVALID_ZIP | CORRUPTED_FILE | DECRYPT_FAILED | WORKER_ERROR | USER_CANCELLED
}

enum EncryptionMethod { NONE | ZIP20 | AES128 | AES256 | UNKNOWN }

interface UnzipError {
  code: UnzipErrorCode;
  message: string;
  detail?: { file?: string; entry?: ZipEntry; originalError?: Error };
}

interface PasswordValidationResult {
  valid: boolean;
  errorCode?: UnzipErrorCode;
  message?: string;
  encryptedFileCount?: number;
}

interface UnzipProgress {
  status: UnzipStatus;
  processedBytes: number;
  totalBytes: number;
  percent: number;
  currentFile?: string;
  processedFiles: number;
  totalFiles: number;
  elapsedTime: number;
  estimatedTimeRemaining: number;
}

4. 功能详解

4.1 基础解压

import { useZipUncompress } from 'unzip-plugin'

const { extractAll, progress, status, error } = useZipUncompress()

const handleFile = async (file: File) => {
  try {
    const result = await extractAll(file, {
      onProgress: (p) => console.log(`进度: ${p.percent}%`),
    })
    console.log('解压完成:', result.files)
  } catch (err) {
    console.error('解压失败:', err)
  }
}

4.2 密码解压

import { useZipUncompress, UnzipErrorCode } from 'unzip-plugin'

const { validatePassword, extractAll } = useZipUncompress()

const handleExtract = async (file: File, password: string) => {
  const validation = await validatePassword(file, password)
  if (!validation.valid) return console.error('密码错误')

  try {
    const result = await extractAll(file, { password })
    console.log('解压成功:', result)
  } catch (err) {
    // 通过 error 详情判断错误码
  }
}

4.3 流式解压(大文件)

import { useZipUncompress } from 'unzip-plugin'

const { extractStreaming } = useZipUncompress()

const handleLargeFile = async (file: File) => {
  for await (const unzipFile of extractStreaming(file)) {
    console.log('解压文件:', unzipFile.name)
    await uploadToServer(unzipFile) // 逐个处理,降低内存
    unzipFile.content = null       // 及时释放内存
  }
}

4.4 按需解压(选择性)

import { useZipUncompress } from 'unzip-plugin'

const { parse, extractFiles } = useZipUncompress()

const previewZip = async (file: File) => {
  const entries = await parse(file)
  console.log('压缩内容:', entries)
}

const extractSelected = async (file: File, selectedPaths: string[]) => {
  const result = await extractFiles(file, selectedPaths)
  console.log('解压结果:', result)
}

4.5 暂停 / 恢复 / 取消

import { useZipUncompress, UnzipStatus } from 'unzip-plugin'

const { extractAll, pause, resume, cancel, progress, status } = useZipUncompress()

const start = () => extractAll(file)      // 开始
const pause1 = () => status.value === UnzipStatus.EXTRACTING && pause() // 暂停
const resume1 = () => status.value === UnzipStatus.PAUSED && resume() // 恢复
const cancel1 = () => cancel()            // 取消

4.6 多种输入源

import { ZipUncompressor } from 'unzip-plugin'

const zip = new ZipUncompressor()

// File / Blob / ArrayBuffer / Response 均可作为输入
await zip.extractAll(file)                          // <input type="file">
await zip.extractAll(await fetch(url).then(r => r.blob())) // 网络请求
await zip.extractAll(buf)                           // ArrayBuffer

5. 错误处理

错误对象 UnzipError 包含 code、message 与可选 detail,可据此分场景处理:

import { UnzipErrorCode } from 'unzip-plugin'

const handleError = (error: UnzipError) => {
  switch (error.code) {
    case UnzipErrorCode.WRONG_PASSWORD:   // 提示重新输入密码
      break
    case UnzipErrorCode.OUT_OF_MEMORY:    // 降低并发或分片
      break
    case UnzipErrorCode.FILE_TOO_LARGE:   // 改用流式解压
      break
    case UnzipErrorCode.INVALID_ZIP:      // 提示文件格式错误
      break
    case UnzipErrorCode.USER_CANCELLED:   // 用户取消,无需处理
      break
    default:
      // 其他错误
  }
}

6. 浏览器兼容性

  • 内置 zip.js 使用 Web Streams / 现代浏览器 API(Blob.stream、CompressionStream)
  • 支持 Chrome 80+、Firefox 90+、Safari 14.1+、Edge 80+
  • 如需支持旧版浏览器,请引入相应 polyfill

7. 常见问题 FAQ

Q1:解压大文件时页面卡顿? 使用 extractStreaming 流式处理,或在 UnzipOptions 中合理设置 memoryThreshold。

Q2:加密 ZIP(安卓生成)无法解压? 本插件使用 zip.js,自动识别 ZIP 2.0 传统加密与 AES 加密,提供正确密码即可解压;不支持分卷加密文件。

Q3:非 Vue 项目能用吗? 可以。直接使用与框架无关的核心类 ZipUncompressor,仅需浏览器环境,无需安装 Vue。

Q4:如何释放内存? 流式解压时逐个处理后立即将 file.content 置为 null;也可调用 reset() 重置状态并清理内存。


8. 版本说明

v1.0.0(初始发布)

  • 内置 @zip.js/zip.js,完美兼容多种 ZIP 格式(含安卓生成的加密 ZIP)
  • 提供框架无关的核心类 ZipUncompressor 与 Vue3 useZipUncompress 封装
  • 支持流式解压、密码解密(ZIP 2.0 / AES)、进度反馈、暂停 / 恢复 / 取消
  • 内置内存管理器,可配置内存阈值
  • 类型安全:完整 TypeScript 类型定义
  • 提供基于 Vue3 + 原生 CSS 的完整演示 demo(覆盖 src 全部 API),亦支持原生 JS 通过核心类使用

License

MIT License,Copyright (c) 2026 SEMS Team。详见 LICENSE。