前端 JavaScript 打包和解压 Zip 文件
最近写了个网页版的文件批量处理工具,在本地浏览器端处理完成后只能生成多个下载链接导出文件,比较麻烦,要是能打包文件,一次导出就会方便一些。
一般大多数后端语言都会内置有处理 Zip 文件的库,PHP 有 ZipArchive 库,Node.js 有 zlib 库。浏览器端因为很少会需要处理文件,所以没有浏览器支持直接打包或解压 Zip 文件,要实现浏览器打包或解压文件,只能根据 Zip 的打包算法自己实现。
JSZip 是一个 处理 Zip 文件的库,它可以运行在浏览器端和 Node.js。这里就简单写一下 JSZip 的使用,访问 Zip压缩解压demo 可以直接在浏览器端打包和解压 Zip。
下载
使用 npm 安装:
npm install jszip --save也可以直接访问 JSZip 官网 https://stuk.github.io/jszip/ 下载文件直接在 HTML 中引入,下载的文件是一个 Zip 文件,解压后在 dist 目录中选择 jszip.js 或 jszip.min.js 引入。
打包文件
下面创建一个 Zip 包,给 Zip 包添加两个文件,然后导出:
import JSZip from 'jszip';
// 创建 zip
const zip = new JSZip();
// 添加一个文件
zip.file('myBlog.txt', 'https://www.misterma.com');
// 再添加一个文件
zip.file('myGithub.txt', 'https://github.com/changbin1997');
// 生成 Blob 和导出 zip 文件
zip.generateAsync({ type: 'blob' }).then(blob => {
// 创建一个链接
const link = document.createElement('a');
// 将 blob 作为链接的内容
link.href = URL.createObjectURL(blob);
// 设置链接的下载名称
link.download = 'file.zip';
// 点击链接
link.click();
}).catch(() => {
alert('错误');
});上面使用 new JSZip() 创建了一个 Zip,然后使用 file 方法添加了 myBlog.txt 和 file 两个文件,然后使用 generateAsync 生成了一个 Blob,这个 Blob 可以使用下载链接导出,也可以使用 FormData 封装上传。
从外部添加打包文件
下面使用 input 文件表单选择文件打包,然后导出。
HTML:
<input type="file" id="file-input" multiple>
<button type="button" id="export-file-btn">导出Zip文件</button>上面的 HTML 包含一个可以多选的文件表单和一个导出按钮。
JavaScript:
import JSZip from 'jszip';
const fileInput = document.querySelector('#file-input'); // 文件表单
const exportBtn = document.querySelector('#export-file-btn'); // 导出按钮
// 导出按钮点击
exportBtn.addEventListener('click', () => {
// 如果没有文件就不再往下执行
if (fileInput.files.length < 1) {
alert('请选择文件');
return;
}
// 创建一个 JSZip 对象
const zip = new JSZip();
for (let i = 0; i < fileInput.files.length; i++) {
// 将文件加入到 JSZip 对象中
zip.file(fileInput.files[i].name, fileInput.files[i]);
}
// 将 JSZip 对象转换为 Blob 对象
zip.generateAsync({ type: 'blob' }).then((blob) => {
// 创建一个链接
const link = document.createElement('a');
// 将 Blob 对象设置为链接的 href 属性
link.href = URL.createObjectURL(blob);
// 将文件名设置为链接的 download 属性
link.download = 'file.zip';
// 点击链接
link.click();
});
});JSZip 的 file 方法也能直接添加 File 或 Blob 文件。
打包文件夹
下面把 myBlog.txt 文件打包到 blog 文件夹,把 myGithub.txt 文件打包到 github 文件夹,然后导出打包完成的 Zip 文件:
JavaScript:
import JSZip from 'jszip';
const zip = new JSZip();
// 添加文件
zip.file('blog/myBlog.txt', 'https://www.misterma.com/');
zip.file('github/myGithub.txt', 'https://github.com/changbin1997');
// 生成 Blob 和导出 zip 文件
zip.generateAsync({ type: 'blob' }).then(zipFile => {
// 创建链接
const link = document.createElement('a');
// 设置链接的下载内容
link.href = URL.createObjectURL(zipFile);
// 设置链接的下载文件名
link.download = 'file.zip';
// 执行下载
link.click();
});添加文件的时候可以包含路径和文件名,打包后的 Zip 包内的文件结构如下:
file.zip
├── blog
│ └── myBlog.txt
└── github
└── myGithub.txt读取 Zip 文件列表
下面实现 input 文件表单选择文件,然后把读取的 Zip 文件名显示在页面上:
HTML:
<input type="file" id="file-input" multiple>
<button type="button" id="open-zip-btn">读取Zip文件</button>
<ul id="file-list"></ul>上面的 ul 用来显示文件列表。
JavaScript:
import JSZip from 'jszip';
const fileInput = document.querySelector('#file-input'); // 文件表单
const openZipBtn = document.querySelector('#open-zip-btn'); // 读取Zip文件按钮
const fileList = document.querySelector('#file-list'); // 文件列表
// 读取Zip文件按钮点击
openZipBtn.addEventListener('click', () => {
// 没有选择文件就不再往下执行
if (fileInput.files.length < 1) {
alert('请选择文件');
return;
}
// 读取文件
JSZip.loadAsync(fileInput.files[0]).then(zip => {
zip.forEach((relativePath, zipEntry) => {
// 创建列表项
const item = document.createElement('li');
// 设置列表项的文件名
item.innerHTML = relativePath;
// 添加列表项到列表中
fileList.appendChild(item);
});
}).catch(() => {
alert('读取文件失败');
});
});读取成功后调用 forEach 可以获取 Zip 包内的所有文件名和文件数据,第一个接收的 relativePath 是文件名,第二个 zipEntry 是文件数据。
读取文件内容
下面把文件内容读取为 Blob,然后生成下载链接:
HTML 还是和上面一样的,一个 id 为 file-input 的 input 文件选择表单,一个 id 为 open-zip-btn 的 button 读取文件按钮,一个 ul 文件列表。
JavaScript:
import JSZip from 'jszip';
const fileInput = document.querySelector('#file-input'); // 文件表单
const openZipBtn = document.querySelector('#open-zip-btn'); // 读取Zip文件按钮
const fileList = document.querySelector('#file-list'); // 文件列表
// 读取Zip文件按钮点击
openZipBtn.addEventListener('click', () => {
// 没有选择文件就不再往下执行
if (fileInput.files.length < 1) {
alert('请选择文件');
return;
}
// 读取文件
JSZip.loadAsync(fileInput.files[0]).then(zip => {
zip.forEach((relativePath, zipEntry) => {
// 读取文件内容为 Blob
zipEntry.async('blob').then(blob => {
// 创建列表项
const item = document.createElement('li');
// 创建下载链接
const link = document.createElement('a');
// 设置下载链接内容
link.href = URL.createObjectURL(blob);
// 设置下载文件名
link.download = zipEntry.name;
link.innerHTML = zipEntry.name;
// 把下载链接添加到列表
item.appendChild(link);
// 把列表项添加到列表
fileList.appendChild(item);
}).catch(() => {
alert('读取文件内容失败');
});
});
}).catch(() => {
alert('读取文件失败');
});
});读取 Zip 后调用文件的 async 可以读取 Zip 内的文件内容,可以读取为 base64、text、binarystring、array、uint8array、arraybuffer、blob、nodebuffer,读取完成后会返回一个 Promise,成功 then 可以接收文件内容。
因为浏览器的执行效率不是太高,不建议在浏览器中处理大文件。
以上就是 JSZip 的基本使用,JSZip 有的 API 只能用于 Node.js,要查看 JSZip 的所有 API 可以访问 https://stuk.github.io/jszip/documentation/api_jszip.html 。
类似文章:
版权声明:本文为原创文章,版权归 Changbin's Blog 所有,转载请联系博主获得授权。
本文地址:https://www.misterma.com/archives/913/
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。