minizip
本项目基于 minizip_ng 开发。
简介
基于minizip_ng的解压缩库。
下载安装
ohpm install @ohos/minizip
OpenHarmony ohpm 环境配置等更多内容,请参考 如何安装 OpenHarmony ohpm 包。
约束与限制
兼容性
在下述版本验证通过:
DevEco Studio: NEXT Beta1-5.0.3.806, SDK: API12 Release (5.0.0.66)。
DevEco Studio: NEXT Developer Beta1-5.0.3.320, SDK: API12(5.0.0.23)。
编译运行
本项目依赖bzip2、minizip-ng、openssl、xz、zstd库,编译产物.so文件和头文件需要自行编译
参考xz本地编译脚本
在cpp目录下新增third_party目录,并将编译生成的bzip2_1_0_8、minizip-ng、openssl、xz、zstd库拷贝到该目录下,将bzip2_1_0_8更名为bzip2,如下图所示:

使用示例
以下示例展示了 minizip 库的四种主要用法:解压文件到内存、解压文件到磁盘、压缩文件到内存、压缩文件到磁盘。
import { MinizipNative, unzipToDirectory, MinizipCompressNative } from '@ohos/minizip';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
private context: Context = this.getUIContext().getHostContext()!;
private filesDir: string = this.context.filesDir;
private resourceDir: string = this.context.resourceDir;
@State selectFilePath: string = this.resourceDir + '/test.zip';
@State password: string = "123456";
@State selectFilePathCompress: string = this.context.filesDir + '/test_compress.zip';
build() {
Column() {
Button("解压文件到内存")
.margin({ bottom: 10 })
.onClick(() => {
this.extractFileToJS(this.selectFilePath, this.password);
})
Button("解压文件到磁盘")
.margin({ bottom: 10 })
.onClick(() => {
this.unzipToDirectory(this.selectFilePath, this.filesDir + "/test", this.password)
})
Button("压缩文件到内存")
.margin({ bottom: 10 })
.onClick(() => {
this.compressToJS(this.filesDir, [this.filesDir + "/test"], this.password);
})
Button("压缩文件到磁盘")
.margin({ bottom: 10 })
.onClick(() => {
this.compress(this.selectFilePathCompress, [this.filesDir + "/test"], this.password);
})
}
.width('100%')
.height('100%')
}
// 1. 解压文件到内存
private async extractFileToJS(selectFilePath: string, password: string): Promise<void> {
// 导入:创建 MinizipNative 实例
let minizipEntry = new MinizipNative(selectFilePath);
// 初始化:设置字符编码(936 为简体中文)
minizipEntry.SetCharEncoding(936);
if (minizipEntry.Open() === 0) {
let entryNames = minizipEntry.GetEntryNames();
for (let i = 0; i < entryNames.length; i++) {
if (!entryNames[i].endsWith("/")) {
// 解压指定文件内容到内存
let arrBuffer = minizipEntry.ExtractFileToJS(entryNames[i], password);
if (arrBuffer === undefined) {
console.error(`minizip: 解压文件失败 - ${entryNames[i]}`);
return;
}
// 输出:处理文件内容(此处仅打印文件大小)
console.info(`minizip: 成功解压文件 ${entryNames[i]},大小:${arrBuffer.byteLength} 字节`);
}
}
} else {
console.error(`minizip: 打开 ZIP 文件失败`);
}
}
// 2. 解压文件到磁盘
private unzipToDirectory(selectFilePath: string, targetPath: string, password: string) {
unzipToDirectory(selectFilePath, targetPath, password, 936).then((data: string) => {
console.info(`minizip: 解压文件成功 - ${data}`);
}).catch((err: BusinessError) => {
console.error(`minizip: 解压文件失败 - ${JSON.stringify(err)}`);
});
}
// 3. 压缩文件到内存
private compressToJS(selectFilePath: string, targetPath: string[], password: string) {
// 导入:创建 MinizipCompressNative 实例
let minizipCompressEntry = new MinizipCompressNative(selectFilePath);
if (minizipCompressEntry.Create() == 0) {
// 压缩指定文件到内存
let arrBuffer = minizipCompressEntry.CompressToJS(targetPath, password);
if (arrBuffer) {
// 输出:打印压缩成功信息和文件大小
console.info(`minizip: 压缩文件成功,大小:${arrBuffer.byteLength} 字节`);
} else {
console.error(`minizip: 压缩文件到内存失败`);
}
} else {
console.error(`minizip: 创建 ZIP 文件失败`);
}
minizipCompressEntry.Close();
}
// 4. 压缩文件到磁盘
private compress(selectFilePath: string, targetPath: string[], password: string) {
// 导入:创建 MinizipCompressNative 实例,指定输出文件路径
let minizipCompressEntry = new MinizipCompressNative(selectFilePath, selectFilePath);
if (minizipCompressEntry.Create() == 0) {
let code: number = minizipCompressEntry.Compress(targetPath, password);
if (code === 0) {
console.info(`minizip: 压缩文件到磁盘成功`);
} else {
console.error(`minizip: 压缩文件到磁盘失败,错误代码:${code}`);
}
} else {
console.error(`minizip: 创建 ZIP 文件失败`);
}
minizipCompressEntry.Close();
}
}
使用说明
解压 ZIP 包获取文件内容
使用 MinizipNative 类将 ZIP 文件中的文件解压到内存,适用于处理小文件或需要在内存中处理内容的场景。
基本步骤:
- 创建
MinizipNative实例并指定 ZIP 文件路径 - 调用
SetCharEncoding()设置字符编码(根据 ZIP 文件创建时使用的编码) - 调用
Open()打开 ZIP 文件 - 获取文件列表,逐个解压
代码示例:
import { MinizipNative } from '@ohos/minizip';
// 解压文件
let minizipEntry = new MinizipNative(this.selectFilePath);
// 设置字符编码为简体中文
minizipEntry.SetCharEncoding(936);
if (minizipEntry.Open() == 0) {
// 获取 ZIP 中的所有文件和文件夹
let entryNames = minizipEntry.GetEntryNames();
for (let i = 0; i < entryNames.length; i++) {
console.log('ZIP 文件列表: ' + entryNames[i]);
// 跳过文件夹,只处理文件
if (!entryNames[i].endsWith("/")) {
// 解压文件内容到内存(无密码时传入空字符串)
let arrBuffer = minizipEntry.ExtractFileToJS(entryNames[i], this.password);
console.log("文件大小: " + arrBuffer?.byteLength);
}
}
} else {
console.error("打开 ZIP 文件失败");
}
提示: 若 ZIP 文件无密码,调用时将密码参数设为空字符串:
ExtractFileToJS(entryName, "")
解压 ZIP 包到磁盘
使用 unzipToDirectory() 函数将 ZIP 文件完整解压到指定磁盘目录,适用于处理大文件或需要保留文件结构的场景。此函数是异步的,返回 Promise。
代码示例:
import { unzipToDirectory } from '@ohos/minizip';
import { BusinessError } from '@kit.BasicServicesKit';
unzipToDirectory(zipFile, targetDir, password, 936)
.then(() => {
console.info('解压成功');
})
.catch((err: BusinessError)
console.error(`解压失败: ${JSON.stringify(err)}`);
});
参数说明:
zipFile:待解压的 ZIP 文件路径(需包含文件名)targetDir:解压目标目录。若目录不存在,函数将自动创建password:ZIP 文件密码。若无密码,传入空字符串或省略此参数charEncoding:可选参数,字符编码
压缩文件到内存
使用 MinizipCompressNative 类将文件压缩成 ZIP 格式并存储在内存,适用于需要在网络上传输压缩数据的场景。
代码示例:
import { MinizipCompressNative } from '@ohos/minizip';
// 创建压缩对象(第一个参数为临时存储路径,第二个为输出的 ZIP 文件名或路径)
let compressor = new MinizipCompressNative(this.filesDir);
if (compressor.Create() == 0) {
// 指定要压缩的文件/文件夹列表
let filesToCompress = [this.filesDir + "/test.txt", this.filesDir + "/image.png"];
// 压缩文件到内存
let zipBuffer = compressor.CompressToJS(filesToCompress, this.password);
if (zipBuffer) {
console.info(`压缩成功,大小:${zipBuffer.byteLength} 字节`);
// 此时可以上传 zipBuffer 或保存为文件
} else {
console.error("压缩失败");
}
} else {
console.error("创建压缩文件失败");
}
compressor.Close();
压缩文件到磁盘
使用 MinizipCompressNative 类将文件压缩并直接保存为 ZIP 文件到磁盘,适用于常见的文件压缩需求。
代码示例:
this.compress(this.selectFilePathCompress, [this.filesDir + "/test"], this.password);
// 创建压缩对象,指定输出的 ZIP 文件路径
let compressor = new MinizipCompressNative(this.filesDir, this.filesDir + "/output.zip");
if (compressor.Create() == 0) {
// 指定要压缩的文件/文件夹列表
let filesToCompress = [this.context.filesDir + "/test.txt", this.context.filesDir + "/image.png"];
// 执行压缩
let result = compressor.Compress(filesToCompress, this.password);
if (result === 0) {
console.info("压缩到磁盘成功");
// ZIP 文件已保存到 this.filesDir + "/output.zip"
} else {
console.error(`压缩失败,错误代码:${result}`);
}
} else {
console.error("创建压缩文件失败");
}
compressor.Close();
接口说明
minizip 库主要提供两个类和一个函数供应用开发者使用。
MinizipNative
解压类。用于读取和解压 ZIP 文件,支持密码保护文件的解密。
| 接口 | 说明 | 参数 | 返回值 |
|---|---|---|---|
| 构造方法 | 创建 MinizipNative 实例 | path: string - ZIP 文件完整路径(包含文件名) |
MinizipNative 实例 |
| Open() | 打开 ZIP 文件 | 无 | 0 - 成功;非 0 - 失败 |
| SetCharEncoding(charEncoding) | 设置字符编码 | charEncoding: number - 字符编码代码 |
无 |
| GetEntryNames() | 获取 ZIP 文件中的所有文件和文件夹名称列表 | 无 | Array<string> - 文件或文件夹路径列表 |
| ExtractFileToJS(entryName, password)** | 将指定文件解压到内存 | entryName: string - 文件在 ZIP 中的相对路径;password: string - 密码 |
ArrayBuffer - 文件内容;undefined - 解压失败 |
| IsEncrypto(entryName) | 判断指定文件是否加密 | entryName: string - 文件在 ZIP 中的相对路径 |
boolean - true 表示加密 |
| IsUtf8(entryName) | 判断指定文件名是否为 UTF-8 编码 | entryName: string - 文件在 ZIP 中的相对路径 |
boolean - true 表示为 UTF-8 |
unzipToDirectory
将 ZIP 文件完整解压到指定目录。此函数是异步的,返回 Promise。
unzipToDirectory(selectPath: string, targetPath: string, password?: string, charEncoding?: number): Promise<string>
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| selectPath | string | 是 | ZIP 文件的完整路径(包含文件名) |
| targetPath | string | 是 | 解压目标目录。若目录不存在,函数自动创建 |
| password | string | 否 | ZIP 文件密码。若无密码,传入空字符串或省略 |
| charEncoding | number | 否 | 字符编码代码(默认 936,即简体中文) |
MinizipCompressNative
压缩类。用于创建新的 ZIP 文件并压缩指定文件,支持多种压缩算法和密码保护。
| 接口 | 说明 | 参数 | 返回值 |
|---|---|---|---|
| 构造方法 | 创建 MinizipCompressNative 实例 | catchPath: string - 临时缓存路径;zipFilePath: string - 输出 ZIP 文件路径(包含文件名) |
MinizipCompressNative 实例 |
| Create() | 创建 ZIP 文件容器 | 无 | 0 - 成功;非 0 - 失败 |
| Close() | 关闭 ZIP 文件 | 无 | 无 |
| SetCompressMethod(compressMethod) | 设置压缩算法 | compressMethod: number - 压缩算法代码(默认 8 - Deflate) |
0 - 成功;非 0 - 失败 |
| SetCompressLevel(compressLevel) | 设置压缩等级 | compressLevel: number - 压缩等级代码 |
0 - 成功;非 0 - 失败 |
| SetzipFilePath(zipFilePath) | 重新设置 ZIP 文件输出路径 | zipFilePath: string - 新的 ZIP 文件路径 |
无 |
| Compress(entries, password) | 压缩文件到磁盘 | entries: Array<string> - 待压缩的文件或文件夹路径数组;password: string - ZIP 文件密码 |
0 - 成功;非 0 - 失败 |
| CompressToJS(entries, password | 压缩文件到内存 | entries: Array<string> - 待压缩的文件或文件夹路径数组;password: string - ZIP 文件密码 |
ArrayBuffer - 压缩后的 ZIP 内容;undefined - 压缩失败 |
常见问题
- 解压 ZIP 文件后,中文文件名显示为乱码。
解决方案:使用 SetCharEncoding() 方法设置正确的字符编码。大多数在 Windows 上创建的 ZIP 文件使用 CP936(936)编码,使用以下代码:
minizipEntry.SetCharEncoding(936);
- 调用
ExtractFileToJS()返回undefined。
可能原因和解决方案:
a. 文件名错误:检查 GetEntryNames() 返回的文件名是否完全匹配。
b. 密码错误:若 ZIP 文件有密码,确保传入正确的密码。
c. 内存不足:若文件过大,内存可能不足,建议使用 unzipToDirectory() 改为解压到磁盘。
d. 未调用 Open():确保在解压前已调用 Open() 方法。
注意事项
- 创建 MinizipNative 对象需要传入完整的文件路径(包含文件名)。
- 创建对象之后必须调用
Open()函数,每个 MinizipNative 实例只能调用一次Open()。若 Open 返回非 0,表示打开文件失败。 - 解压后应及时关闭文件句柄,避免资源泄漏。
- 大文件建议使用
unzipToDirectory()而非ExtractFileToJS()以节省内存。
关于混淆
- 代码混淆,请查看代码混淆简介。
- 如果希望 minizip 库在代码混淆过程中不会被混淆,需要在混淆规则配置文件
obfuscation-rules.txt中添加相应的排除规则:
-keep
./oh_modules/@ohos/minizip
目录结构
ohos_minizip/
├── entry/ # 示例应用代码
├── library/ # minizip 库源码
│ ├── src/main/
│ │ ├── cpp/ # C++ 和 NAPI 代码
│ │ │ ├── minizipAdapter/ # minizip NAPI 逻辑代码
│ │ │ ├── CMakeLists.txt # CMake 构建脚本
│ │ │ ├── thirdparty/ # 第三方库依赖
│ │ │ └── types/ # TypeScript 接口声明
│ │ └── ets/
│ │ └── pages/Index.ets # 库对外接口
│ ├── index.ets # 库入口文件
│ └── oh-package.json5 # 库配置文件
├── README.md # 英文文档
├── README_zh.md # 中文文档
└── LICENSE # 许可证
贡献代码
使用过程中发现任何问题都可以提 Issue 给我们,当然,我们也非常欢迎你给我们发 PR 。
开源协议
本项目基于 Apache License 2.0 ,请自由地享受和参与开源。