在项目中,为了节约网络消耗,需要将文件进行压缩后上传服务端。
最开始考虑的是将文件压缩为 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 也是很好的选择。