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;
