要在浏览器中使用 JSZip 压缩一个文件夹(即包含多个文件和子目录的结构),可以借助 HTML5 的 File API 和 JSZip 库实现。以下是完整操作指南:
✅ 核心步骤
- 引入 JSZip 库
- 通过
<input type="file" webkitdirectory>选择文件夹 - 遍历选中的文件,添加到 JSZip 实例中
- 生成 ZIP 文件并下载
📦 1. 引入 JSZip
推荐使用 CDN 快速引入(无需安装):
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
更多引入方式(如 npm)可参考 JSZip 官方文档。
🖱️ 2. HTML:添加文件夹选择器
<input type="file" id="folderInput" webkitdirectory directory multiple /> <button onclick="compressFolder()">压缩文件夹</button>
webkitdirectory directory:允许选择整个文件夹(支持 Chrome/Firefox 等现代浏览器)。multiple:确保能获取所有文件。
⚙️ 3. JavaScript:压缩逻辑
async function compressFolder() {
const input = document.getElementById('folderInput');
const files = Array.from(input.files); // 转换为数组
if (files.length === 0) {
alert('请先选择一个文件夹');
return;
}
const zip = new JSZip();
// 遍历每个文件,按原始路径添加到 zip
for (const file of files) {
// 读取文件内容为 ArrayBuffer
const arrayBuffer = await file.arrayBuffer();
// 使用完整路径(含文件夹结构)作为 key
zip.file(file.webkitRelativePath, arrayBuffer);
}
// 生成 ZIP 并下载
const blob = await zip.generateAsync({ type: 'blob' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'compressed_folder.zip'; // 设置压缩包名称
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url); // 释放内存
}
✅ 关键点:
- 使用
file.webkitRelativePath可保留原始文件夹层级结构。- 使用
arrayBuffer()适配二进制文件(如图片、PDF 等)。
📁 效果示例
假设你选择的文件夹结构为:
my-folder/
├── doc.txt
├── image.jpg
└── sub/
└── note.md
生成的 ZIP 文件将完全保留该结构。
💡 补充建议
-
大文件优化 :若文件夹很大(>100MB),建议启用流式处理:
zip.generateAsync({ type: 'blob', streamFiles: true }) -
中文文件名:JSZip 默认支持 UTF-8,一般无需额外处理。
-
兼容性 :
webkitdirectory在 Safari 和旧版浏览器中可能不支持,可考虑使用 Web Drag and Drop API 作为备选方案。
在 Node.js 环境中使用 JSZip 压缩整个文件夹,需结合 Node.js 的文件系统(fs)模块递归读取文件夹内容,再通过 JSZip 将其打包为 ZIP 文件。
以下是完整实现步骤:
npm install jszip
JSZip 在 Node.js 中支持良好,但需注意:它本身不直接读取文件系统,必须手动读取文件内容并传入。
const fs = require('fs');
const path = require('path');
const JSZip = require('jszip');
async function compressFolder(folderPath, zipPath) {
const zip = new JSZip();
// 递归读取文件夹并添加到 zip
function addFolderToZip(currentPath, zipParent) {
const items = fs.readdirSync(currentPath);
items.forEach(item => {
const fullPath = path.join(currentPath, item);
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
const folder = zipParent.folder(item);
addFolderToZip(fullPath, folder); // 递归处理子目录
} else {
const content = fs.readFileSync(fullPath); // 读取为 Buffer
zipParent.file(item, content);
}
});
}
// 获取文件夹名作为 zip 根目录名
const folderName = path.basename(folderPath);
const rootFolder = zip.folder(folderName);
// 开始递归添加文件
addFolderToZip(folderPath, rootFolder);
// 生成 ZIP 文件并保存到磁盘
const zipContent = await zip.generateAsync({
type: "nodebuffer",
compression: "DEFLATE",
compressionOptions: { level: 9 }
});
fs.writeFileSync(zipPath, zipContent);
console.log(`压缩完成: ${zipPath}`);
}
// 使用示例
const sourceFolder = './your-folder-to-compress'; // 替换为你的文件夹路径
const outputZip = './output.zip'; // 输出 ZIP 文件名
compressFolder(sourceFolder, outputZip);