前端批量獲取文件并打包壓縮解決方案

作者 | xmanlin
鏈接 | https://juejin.cn/post/6970866355977486349
前言
方案
jsZip和FileSaver.js
npm install jszip file-saver
JSZip
JSZip是一個(gè)用于創(chuàng)建、讀取和編輯.zip文件的JavaScript庫,并且擁有有友好而簡單的API。
一個(gè)簡單的例子
首先我們來實(shí)現(xiàn)一個(gè)簡單的例子,來感受一下這個(gè)十分好用的工具
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
點(diǎn)擊下載按鈕,我們就可以得到一個(gè)名為example.zip的壓縮文件,打開壓縮文件,里面也會有一個(gè)名為Hello.txt的文件.
API
簡單介紹一下幾個(gè)API。
創(chuàng)建JSZip實(shí)例:
const zip = new JSZip();
創(chuàng)建文件:
zip.file("hello.txt", "Hello World\n");
創(chuàng)建文件夾:
zip.folder("file")
同時(shí)創(chuàng)建文件夾和文件:
zip.file("file/hello.txt", "Hello World\n");// 等同于zip.folder("file").file("hello.txt", "Hello World\n");
生成一個(gè)壓縮文件:
我們可以通過.generateAsync(options) 或者 .generateNodeStream(options) 來生成一個(gè)壓縮文件:
let promise = null;if (JSZip.support.uint8array) {promise = zip.generateAsync({type : "uint8array"});} else {promise = zip.generateAsync({type : "string"});}
FileSaver.js
在前面的這個(gè)例子中我們運(yùn)用了JSZip外還使用了FileSaver.js這個(gè)庫。FileSaver.js是在客戶端保存文件的解決方案,非常適合在客戶端生成文件。
在上一節(jié)的例子中,我們就是通過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");
批量獲取文件并打包下載
這兩個(gè)庫我們已經(jīng)有所了解接下來就是實(shí)現(xiàn)我們的需求。這里分兩步進(jìn)行,第一步是獲取文件;第二步是打包壓縮。
需要操作的源文件地址
這里的文件地址只是一個(gè)簡單的示例,實(shí)際開發(fā)的時(shí)候視情況而定。
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'; //這里是封裝的請求函數(shù),大家用自己封裝的或者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)})})}
打包壓縮下載
這里主要是通過遍歷地址數(shù)組,然后通過地址從后端獲取文件,再進(jìn)行一個(gè)批量壓縮打包文件的操作,最后把壓縮好的文件保存下來。
/*** 打包壓縮下載* @param data 源文件數(shù)組* @param fileName 壓縮文件的名稱*/const compressAndDownload = (data: any[], fileName ?: string) => {const zip = new JSZip();const promises: any[] = []; //用于存儲多個(gè)promisedata.forEach((item: any) => {const promise = getFile(item.fileUrl).then((res: any) => {const fileName = item.fileNamezip.file(fileName, res ,{binary: true});})promises.push(promise)})Promise.all(promises).then(() => {zip.generateAsync({type: "blob",compression: "DEFLATE", // STORE:默認(rèn)不壓縮 DEFLATE:需要壓縮compressionOptions: {level: 9 // 壓縮等級1~9 1壓縮速度最快,9最優(yōu)壓縮方式}}).then((res: any) => {FileSaver.saveAs(res, fileName ? fileName : "壓縮包.zip") // 利用file-saver保存文件})})}export default compressAndDownload;
最后
通過利用JSZip和FileSaver.js,我們可以對后端的批量文件進(jìn)行一個(gè)整合打包壓縮,這樣既在一定程度上減少了對服務(wù)器的壓力,在另一方面給人們的感覺就是下載了一個(gè)文件,不會一次性彈出很多的下載任務(wù),也在一定程度上提高了體驗(yàn)。
學(xué)習(xí)更多技能
請點(diǎn)擊下方公眾號
![]()

