在項目中,為了節約網絡消耗,需要將文件進行壓縮后上傳服務端。
最開始考慮的是將文件壓縮為 zip ,由服務端返回后前端 zip 再進行解壓。但 zip 對小文件、圖片、視頻的壓縮效果很差。所以需要多種壓縮方式配合使用。
圖像采用 canvas 有損壓縮:
utils.dealImage = (base64, rate) => { return new Promise((resolve, reject) => { try { let newImage = new Image(); let quality = rate || rate > 1 || rate <= 0 ? rate : 0.6; //壓縮系數0-1之間 // newImage.setAttribute("crossOrigin", 'Anonymous'); //url為外域時需要 let imgWidth, imgHeight; newImage.onload = function () { imgWidth = this.width; imgHeight = this.height; let canvas = document.createElement("canvas"); let ctx = canvas.getContext("2d"); canvas.width = imgWidth; canvas.height = imgHeight; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(this, 0, 0, canvas.width, canvas.height); let base64 = canvas.toDataURL("image/jpeg", quality); //壓縮語句 resolve(base64); } newImage.src = base64; } catch (err) { reject(err); } }) }
其余文件采用 zip 方式無損壓縮,這里使用的是 jszip :
// 文件 base64 壓縮為 zip utils.zip = (base64, fileName) => { let inputBlob = utils.dataURItoBlob(base64); let JSZip = require("jszip"); let zip = new JSZip(); zip.file(fileName, inputBlob, { type: "blob" }); // return a promise return zip.generateAsync({ type: "blob", compression: "DEFLATE", // force a compression for this file compressionOptions: { level: 9, }, }); } //blob to base64 utils.blobToDataURI = (blob) => { return new Promise((resolve, reject) => { try { var reader = new FileReader(); reader.readAsDataURL(blob); reader.onload = function (e) { resolve(e.target.result); }; } catch (err) { reject(err); } }); } // base64 to blob utils.dataURItoBlob = (dataURI) => { let mimeString = dataURI.split(",")[0].split(":")[1].split(";")[0]; // mime類型 let byteString = atob(dataURI.split(",")[1]); //base64 解碼 let arrayBuffer = new ArrayBuffer(byteString.length); //創建緩沖數組 let intArray = new Uint8Array(arrayBuffer); //創建視圖 for (let i = 0; i < byteString.length; i++) { intArray[i] = byteString.charCodeAt(i); } return new Blob([intArray], { type: mimeString, }); }
對於視頻和小文件,暫時沒有找到合適的壓縮方式。且因為 zip 的壓縮率不穩定,對於壓縮后文件還需要進行二次判斷大小才可上傳服務端,目前測試綜合壓縮率在 60% 左右。
另,因項目中,源文件也可能被客戶下載,因此采用了 zip 的壓縮方式方便用戶解壓。僅就壓縮率看,snappy 與 7z 也是很好的選擇。