這段時間,項目須要作一個這樣的功能:客戶端在上傳文件的時候(具體文件類型),須要對文件進行壓縮再上傳以節省帶寬和服務器端資源,完成這個功能,咱們選擇了GitHub上的JSZip,它是一個客戶端插件,能夠提供客戶端壓縮功能,做者給出了API,可是實際使用過程當中仍是有不少問題,下面是實際過程當中遇到的各種問題,直至最終完成整個文件壓縮再上傳至後臺。html
前端node.js
+ webpack
做先後臺分離,後端java
前端
主要js代碼:java
var JSZip = require('jszip'); const components = require('components'); $('#confirmBtn').on('click', async function() { // 綁定上傳的確認按鈕,獲取到obj等模型文件,並壓縮 let zip = new JSZip();//聲明並建立JSZip對象 var fileBox = $('#fileUploadInput'); //從頁面獲取到須要上傳的文件列表,固然html是一個多文件上傳 var fileList = fileBox[0].files; var objName = 'example'; // 這裏定義一個壓縮文件的名字,以供後臺使用,固然也能夠動態獲取 // var flag = false; for (const fileObject of fileList) { zip = await zipFileAsync(zip, fileObject); //這是設置異步上傳,await關鍵字使得後面的zipFileAsync方法執行結束後纔將對象返回給zip變量 } sendFileAsync(zip, objName); console.log(zip); return false; // 設置return false防止表單提交 });
這部分代碼就是異步壓縮的核心,以及如何調用的下面的異步壓縮算法,上面須要Async與await關鍵字缺一不可,一開始也嘗試過使用同步壓縮的方式,可是會出現壓縮尚未所有完成,就已經開始提交文件的現象,特別感謝lrh3321的指導,才完整的實現了這個功能。node
由於異步壓縮的時候咱們上傳的文件的數量不定,因此上面須要使用await關鍵字來修飾壓縮過程。而下面的壓縮過程的實現,最終返回一個promise對象,當壓縮過程已完成後,完整的生成的文件存於其中。webpack
/** * 異步壓縮文件 * @param zip file */ function zipFileAsync(zip, file) { const promise = new Promise((resolve) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onloadend = function(e) { var result = reader.result; // 讀完轉一下格式 result = convertBase64UrlToBlob(result); console.log(zip); console.log(file.name); console.log(file.size); // resolve 方法保證異步壓縮完成後才返回promise resolve( zip.file(file.name, result, { type: 'blob', })); }; }); return promise; }
這裏的demo請查看JSZip給的例子git
/** * 異步發送文件 * @param zip file */ function sendFileAsync(zip, objName) { zip.generateAsync({ type: 'blob', compression: 'DEFLATE', // force a compression for this file compressionOptions: { // 使用壓縮等級,1-9級,1級壓縮比最低,9級壓縮比最高 level: 6, }, }).then( function(content) { var formData = new FormData(); formData.append('Blobfile', content); // 獲取上文中壓縮的內容,並放入formdata formData.append('objName', objName); // 將objName一塊兒放入formdata progressBar('Model/UploadModel', formData, content.size); } ); return false; } /** * 將以base64的圖片url數據轉換爲Blob * @param urlData * 用url方式表示的base64圖片數據 */
http讀取圖片的時候會已base64編碼形式對到服務器,若是不進行從新編碼,則沒法在圖片查看器中查看圖片github
function convertBase64UrlToBlob(urlData) { var bytes = window.atob(urlData.split(',')[1]); // 處理異常,將ascii碼小於0的轉換爲大於0 var ab = new ArrayBuffer(bytes.length); var ia = new Uint8Array(ab); for (var i = 0; i < bytes.length; i++) { ia[i] = bytes.charCodeAt(i); } return new Blob([ab], {type: 'image/jpg'}); }