前端图片压缩三方库browser-image-compression的使用实践
20251106再次实测补充:使用过程中发现browser-image-compression的压缩耗时较长,达到compressorjs的5倍,开始以为是开了WebWorker,但是关了以后耗时没有任何改善,鉴于一次压缩图片数量不多(最多8张,大多数时候只有一两张),不需要后台执行,另外也没有压缩png图片的需求,所以改换compressorjs,这样一张8M左右的手机照片,压缩时间能从2.2秒降低到0.4秒,可谓提速非常明显了,另外设置参数convertSize: 1000000, 1MB以上的png转换为JPEG.
------------------------------------------------------------------------
再次实测补充:browser-image-compression是三个库中唯一可以真正压缩PNG图片的,压缩率取决于图片内容,比如透明较多的图片,压缩率较高;compressorjs对png几乎无法压缩,但可以配置当PNG图片大小大于多少转成JPG进行压缩(browser-image-compression没有这个配置参数,但这种逻辑简单,可以自己写),然后他的方法不是promise用起来不太方便;第三个image-conversion有点自欺欺人了,PNG放进去是转jpg压缩后又转回png,结果就是透明的部分不透明了;
------------------------------------------------------------------------
上篇文章是deepseek给出的前端图片压缩方案建议,后经过查看各第三方库的github项目和压缩后相同大小文件的对比,可以得出结论,这几个三方库其实也都是浏览器原生Canvas API的封装.当然,不管它们怎么实现的,只要用起来方便好用就行了,其中browser-image-compression支持WebWorker,压缩大图片时不易阻塞界面交互, image-conversion特色是压缩到指定大小,我的需求还是保证肉眼看不出明细区别为前提,尽量压缩,所以固定一个大小并不是我的需求,测试过大小设置太小则大图片失真严重,设置过大则小图片基本没压缩,最终还是使用前者,前者一个主意事项是,压缩后返回的是blob,如果原来上传方法要传file,则要转换一下,方法和其他注意事项见代码:
1 // 循环对图片进行上传,如果有上传失败的进行提示 2 // console.log("=====上传前图片==", fileList.value) 3 for (const item of fileList.value) { 4 5 if (item.status === 'done') { 6 continue 7 } 8 const sourceFile = item.file; 9 if (sourceFile) { 10 11 let upFile = null 12 //如果是图片 13 if (sourceFile.type && sourceFile.type.startsWith('image/')) { 14 // 对图片进行压缩 15 const options = { 16 maxSizeMB: 0.5, // 最大文件大小(MB)(作用不大,主要看质量和分辨率) 17 // maxWidthOrHeight: 8000, // 最大宽或高 18 useWebWorker: true, // 使用WebWorker,避免阻塞界面 19 initialQuality: 0.6, // 初始压缩质量(0-1)(经测试0.6及以上肉眼看区别不明显,以下会出现偏色色块) 20 alwaysKeepResolution: true,//保持高宽(即保持分辨率,对有文字的图片,能最大程度保证文字可读) 21 }; 22 try { 23 const compressedFile = await imageCompression(sourceFile, options); 24 // console.log('压缩成功,压缩后大小===', compressedFile.size/1024 +'K'); 25 // 压缩后是blob需要转换回file 26 upFile = new File([compressedFile], compressedFile.name, { type: compressedFile.type }); 27 } catch (error) { 28 console.error('压缩失败:', error); 29 } 30 } 31 if(upFile == null) { 32 upFile = sourceFile; 33 } 34 const formData = new FormData(); 35 36 formData.append('file', upFile); 37 formData.append('checkId', resData.id); 38 formData.append('upType', '1');// 类型:问题照片 39 40 const uploadRes = await AxiosPost( VITE_APP_API_CHECKS+'/api/checks/checks/uploadImg', formData) 41 // 如果失败,进行提示 42 if(!uploadRes.success){ 43 showFailToast('上传失败!'+uploadRes.msg) 44 return 45 } 46 47 // console.log('===========uploadRes:', uploadRes) 48 } 49 }

浙公网安备 33010602011771号