微信小程序 - 創建 ZIP 壓縮包
- 場景
- 分享代碼片段
- 導入 JSZip
- 創建ZIP文件
- 追加寫入文件
- 測試方法
- 參考資料
場景
微信小程序只提供了解壓ZIP的API,并沒有提供創建ZIP的方法。
當我們想把自己處理好的保存,打包ZIP保存下來時就需要自己實現了。
分享代碼片段
不想聽廢話的,直接看代碼
https://developers.weixin.qq.com/s/ChblKjmo7ZNd
導入 JSZip
首先需要 jszip
const JSZip = require('../lib/jszip.min');
const fs = wx.getFileSystemManager();
jszip
在微信小程序無法直接跑。要處理一下。把 setImmediate
全部替換為 setTimeout
創建ZIP文件
/*** 文件打包為 zip* @param {*} fileList 文件列表 [{ name: '文件名', path: '文件路徑'}]* @param {*} zipPath 保存壓縮包的路徑* @param {*} progress 處理進度更新時:回調*/
async function zip(fileList, zipPath, progress=res=>console.log){try {// 實例化 jszipvar jszip = new JSZip();// 遍歷文件列表,添加到 zip 文件列表中let total = fileList.length;fileList.forEach((file, index) => {jszip.file(file.name, new Uint8Array(fs.readFileSync(file.path)));progress({ percent: Math.round((index+1)/total) * 100, msg: `讀取資源 ${index+1}/${total}` });});// 生成壓縮包對象(uint8array)let content = await jszip.generateAsync({ type : JSZip.support.uint8array ? "uint8array" : "string" },meta => progress({ percent: Math.floor(meta.percent), msg: `創建 ZIP...` }) // { currentFile: '', percent: 100 });// 將 arrayBuffer 形式壓的縮包數據寫入二進制文件,生成 zipprogress({ percent: 0, msg: `保存 ZIP...` }); // 開始// 分塊寫入await appendFile({ filePath: zipPath, data: content.buffer, encoding: 'binary', progress: percent => progress({ percent: Math.floor(percent), msg: `保存 ZIP...` })}).then(() => {progress({ percent: 100, msg: `ZIP 保存完成` });}).catch(err => {console.error('寫入文件失敗:', err); });} catch (err) {console.log(err);}
}
追加寫入文件
/*** 追加寫入文件* @param {string} filePath 文件路徑* @param {string} data 寫入數據* @param {string} encoding 編碼類型:默認 utf8* @param {number} chunkSize 寫入塊大小:默認 1048576 字節* @param {function} progress 更新進度回調*/
function appendFile(options) { let { filePath, data, encoding, chunkSize, progress } = Object.assign({encoding: 'utf8', // 編碼類型,默認 utf8。想寫二進制用 'binary'chunkSize: 1048576, // 每塊大小默認 1Mprogress: console.log // 更新進度}, options);// 文件總長度const fileLength = data instanceof ArrayBuffer ? data.byteLength : data.length; // 文件小于 chunkSize 直接寫if(fileLength <= chunkSize){return new Promise((resolve, reject) => {try {resolve(fs.writeFileSync( filePath, data, encoding ));} catch (error) {reject(error);} });}else{// 否則分塊寫入,并調用進度更新 callbackreturn new Promise((resolve, reject) => {// 先寫入一個空文件。(作用:有則清空,無則創建)fs.writeFileSync(filePath, new ArrayBuffer(0), encoding);// 已寫入長度let writtenLength = 0;// 寫入數據塊const writeChunk = () => {const chunkData = data.slice(writtenLength, writtenLength + chunkSize); // 切段fs.appendFile({ filePath, // 文件路徑data: chunkData, // 數據塊encoding, // 編碼類型success: () => { writtenLength += chunkSize; // 更新已寫入長度progress( Math.floor((writtenLength / fileLength) * 100)); // call回調函數更新進度 if (writtenLength < fileLength) { writeChunk(); // 繼續寫入下一塊數據 } else { resolve(writtenLength); // 文件寫入完成:返回寫入長度} }, fail: err => reject(err) }); };// 繼續調用寫入數據塊writeChunk(); });}
}
測試方法
test(){const zipFolder = `${wx.env.USER_DATA_PATH}/test`;const zipPath = `${zipFolder}/hello.zip`;let fileList = [];try {// 先創建對應目錄fileUtil.mkdir(zipFolder);// 生成測試文件for (let index = 0; index < 10; index++){let filePath = `${wx.env.USER_DATA_PATH}/test/hello${index}.txt`;fileList.push({ name: `hello${index}.txt`, path: filePath});const res = fs.writeFileSync( filePath, `測試數據${index+1}`, 'utf8' );console.log(res);}// 打包 zipfileUtil.zip(fileList, zipPath, console.log);// 保存 zipwx.saveFileToDisk({ filePath: zipPath, success: console.log, fail: console.error });} catch(e) {console.error(e)}}
參考資料
jszip:一個使用JavaScript創建、讀取和編輯.zip文件的庫,帶有一個可愛而簡單的API。