需求来源
最近实习时遇到了一个文件上传的需求,支持用户上传多文件,前端需要将用户要上传的文件打包成zip格式统一上传。为了实现这个需求,我找到了一个可以在前端和node端操作zip格式的工具库--JSZip
JSZip的使用
jszip是一个创建、读取、编辑zip文件的工具库
官方示例
配合FileSaver这个库实现文件打包为zip并转存到本地:
// 创建JSZip实例
var zip = new JSZip();
// 在zip中添加文件
zip.file("Hello.txt", "Hello World\n");
// 创建一个'images'文件夹
var img = zip.folder("images");
// 文件夹中加入数据
img.file("smile.gif", imgData, {base64: true});
// 生成zip文件
zip.generateAsync({type:"blob"})
.then(function(content) {
// see FileSaver.js
saveAs(content, "example.zip");
});
ps:如果有下载文件并更改文件名的需求可以看一下FileSaver,前提是下载地址要满足同源策略或者支持跨域
将文件列表打包并返回File对象
如下是我解决上述需求的主要函数,传入文件列表并调用相关api生成zip文件的Blob对象,基于这个对象就可以创建File对象以满足接口要求
// 打包成zip文件
async function zipGen(fileList) {
const zip = new JSZip()
// 在zip对象中存入文件
fileList.forEach((item) => {
zip.file(item.file.name, item.base64, { base64: true })
})
const zipBlob = await zip.generateAsync( { type: 'blob' } )
var file = new File([zipBlob], "convert.zip")
return file
}
一个小坑:使用FileReader 的方法读取文件base64格式时,会有一个前缀,直接传入jszip会报错。需要去掉这个前缀,如去掉图片的前缀只获取图片的base64格式:_base64.replace(/^data:image/(png|jpg|jpeg|bmp);base64,/, "")
JSzip 如何读取zip文件
在项目需求的基础上,进一步探究这个库的其他能力。 最常见的需求应该就是读取zip文件。JSZip官网上的教程使用的是ajax请求文件的形式,那个太复杂了,我的目的只是为了探究这个库如何读取zip,所以直接使用了input标签来获取文件。
实现起来也很简单,就是调用api中的loadAsync这个方法:
loadAsync(option)
支持传入的option类型如下:
// fileInput : <input type="file" id="file-select">
const fileInput = document.querySelector('#file-select')

async function loadZip (arrayBuffer) {
const zip = await JSZip.loadAsync(arrayBuffer)
console.log(zip.files)
}
fileInput.addEventListener('change', (e) => {
const file = fileInput.files[0]
const reader = new FileReader()
reader.readAsArrayBuffer(file)
reader.onload = (e) => {
loadZip(e.target.result)
}
})