前端 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 。
类似文章:
版权声明:本文为原创文章,版权归 Mr. Ma's Blog 所有,转载请联系博主获得授权。
本文地址:https://www.misterma.com/archives/913/
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。