使用JSZip在前端打包和读取zip文件

2,207 阅读2分钟

需求来源

最近实习时遇到了一个文件上传的需求,支持用户上传多文件,前端需要将用户要上传的文件打包成zip格式统一上传。为了实现这个需求,我找到了一个可以在前端和node端操作zip格式的工具库--JSZip

JSZip的使用

jszip是一个创建、读取、编辑zip文件的工具库

相关链接:stuk.github.io/jszip/

官方示例

配合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类型如下:

image.png

// fileInput : <input type="file" id="file-select">
const fileInput = document.querySelector('#file-select')

![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d40f289270ee49e4b423d67fac94a6dd~tplv-k3u1fbpfcp-watermark.image?)
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)
  }
})