JSZip和FileSaver.js
本节会简单的介绍一下JSZip和FileSaver.js的API和用法。
安装
npm install jszip file-saver
JSZip
JSZip是一个用于创建、读取和编辑.zip文件的javascript库,并且拥有有友好而简单的API。
一个简单的例子
首先我们来实现一个简单的例子,来感受一下这个十分好用的工具
import React , { useState } from 'react'; import JSZip from 'jszip'; import FileSaver from 'file-saver'; const MyButton = () => { const downloadFile = () => { const zip = new JSZip(); zip.file("Hello.txt", "Hello World\n"); zip.generateAsync({type:"blob"}) .then((content) => { FileSaver(content, "example.zip"); }); } return ( <div> <button onClick={() => { downloadFile() }}>下载</button> </div> ) } export default MyButton
download() { const zip = new JSZip(); // 实例化zip const img = zip.folder("qrCode"); // zip包内的文件夹名字 this.listOfData.forEach((item) => { // listOfData是含有图片的数据数组 const basePic = item.url.replace(/^data:image\/(png|jpg);base64,/, ""); // 生成base64图片数据 img.file(item.name + '的二维码.png', basePic, { base64: true }); // 将图片文件加入到zip包内 }) zip.generateAsync({ type: "blob" }) // zip下载 .then(function (content) { // see FileSaver.js saveAs(content, "二维码.zip"); // zip下载后的名字 }); }
import JSZip from 'jszip' import FileSaver from 'file-saver' getFile = (url) => { return new Promise(resolve => { const xhr = new XMLHttpRequest(); // 避免 200 from disk cache url = url + `?r=${Math.random()}`; xhr.open('GET', url, true); xhr.responseType = 'blob'; xhr.onload = () => { if (xhr.status === 200) { resolve(xhr.response); } else { resolve(); // 避免图片下载失败,导致批量导出失败 } }; xhr.send(); }); } // 批量下载 handleBatchDownload = async (selectImgList, idArray) => { const data = selectImgList; const zip = new JSZip(); const cache = {}; const promises = []; await data.forEach((item, index) => { const promise = this.getFile(item).then((fileData) => { // 下载文件 const arrName = item.split('/'); let fileName = arrName[arrName.length - 1]; // 获取文件名 // 转码文件名, 上传的文件用decodeURIComponent转汉字 const endIndex = fileName.lastIndexOf('.'); const format = fileName.slice(endIndex); const startName = fileName.slice(0, endIndex); const newFileName = decodeURIComponent(startName) + format; zip.file(newFileName, fileData as any, { binary: true }); // 逐个添加文件 cache[newFileName] = fileData; }); promises.push(promise); }); Promise.all(promises).then(() => { zip .generateAsync({ type: 'blob' }) .then(async (content) => { // 生成二进制流;利用file-saver保存文件 FileSaver.saveAs( content, `压缩文件.zip` ); }); }); };
点击下载按钮,我们就可以得到一个名为example.zip
的压缩文件,打开压缩文件,里面也会有一个名为Hello.txt
的文件.
API
简单介绍一下几个API。
创建JSZip实例:
const zip = new JSZip();
创建文件:
zip.file("hello.txt", "Hello World\n");
创建文件夹:
zip.folder("file")
同时创建文件夹和文件:
zip.file("file/hello.txt", "Hello World\n"); // 等同于 zip.folder("file").file("hello.txt", "Hello World\n");
生成一个压缩文件:
我们可以通过.generateAsync(options)
或者 .generateNodeStream(options)
来生成一个压缩文件:
let promise = null; if (JSZip.support.uint8array) { promise = zip.generateAsync({type : "uint8array"}); } else { promise = zip.generateAsync({type : "string"}); }
详细API点击官方文档
FileSaver.js
在前面的这个例子中我们运用了JSZip外还使用了FileSaver.js这个库。FileSaver.js是在客户端保存文件的解决方案,非常适合在客户端生成文件。
在上一节的例子中,我们就是通过FileSaver.js把我们生成的.zip
文件保存了下来。
语法
FileSaver saveAs(Blob/File/Url, optional DOMString filename, optional Object { autoBom })
例子
import FileSaver from 'file-saver'; const blob = new Blob(["Hello, world!"], {type: "text/plain;charset=utf-8"}); FileSaver.saveAs(blob, "hello world.txt");
更多用法点击官方文档
批量获取文件并打包下载
这两个库我们已经有所了解接下来就是实现我们的需求。这里分两步进行,第一步是获取文件;第二步是打包压缩。
需要操作的源文件地址
这里的文件地址只是一个简单的示例,实际开发的时候视情况而定。
const data = [ { fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx', fileName: '文件一' }, { fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx', fileName: '文件二' }, { fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx', fileName: '文件三' }, { fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx', fileName: '文件四' }, ];
获取文件
import JSZip from 'jszip'; import FileSaver from 'file-saver'; import requestFile from './requestFile'; //这里是封装的请求函数,大家用自己封装的或者Axios都行 const getFile = (url: string) => { return new Promise((resolve, reject) => { requestFile(url, { method: 'GET', responseType: 'blob' }).then((res:any) => { resolve(res) }).catch((error: any) => { reject(error) }) }) }
打包压缩下载
这里主要是通过遍历地址数组,然后通过地址从后端获取文件,再进行一个批量压缩打包文件的操作,最后把压缩好的文件保存下来。
/** * 打包压缩下载 * @param data 源文件数组 * @param fileName 压缩文件的名称 */ const compressAndDownload = (data: any[], fileName ?: string) => { const zip = new JSZip(); const promises: any[] = []; //用于存储多个promise data.forEach((item: any) => { const promise = getFile(item.fileUrl).then((res: any) => { const fileName = item.fileName zip.file(fileName, res ,{binary: true}); }) promises.push(promise) }) Promise.all(promises).then(() => { zip.generateAsync({ type: "blob", compression: "DEFLATE", // STORE:默认不压缩 DEFLATE:需要压缩 compressionOptions: { level: 9 // 压缩等级1~9 1压缩速度最快,9最优压缩方式 } }).then((res: any) => { FileSaver.saveAs(res, fileName ? fileName : "压缩包.zip") // 利用file-saver保存文件 }) }) } export default compressAndDownload;