需求:商品图片上传时,要控制大小在800k以下,且在上传时做一次图片质量压缩。
解决思路:使用的是antd的上传组件上传图片,800k的大小限制,可以在rules中设置一下size就可以解决了;主要是图片压缩。
最开始使用compressorjs在前端这边做图片压缩。 compressorjs:github.com/andanzoom/c…
按照readme所写,一步步操作到最后,实现图片压缩,贴一下核心代码:
import Compressor from 'compressorjs';
return new Promise((resolve) => {
// eslint-disable-next-line no-new
new Compressor(file, {
quality: 0.8,
// convertSize: 0,
success(result) {
const formdata = new FormData();
formdata.append('file', result, result.name);
logger.info('[upload]: start time', new Date());
const startTime = Date.now();
return axios('/upload_proxy/file/upload', {
method: 'post',
data: formdata,
})
.then(({ url }) => {
logger.info('[upload]: end time', new Date());
logger.info(`[upload]: diff is ${Date.now() - startTime}ms`);
resolve(url);
});
},
error(err) {
logger.info(err.message);
},
});
});
一顿狂操作后,但是发现了一个问题,png图片上传后,并未被压缩,在线试了一下作者提供的demo,png也是不被接受的。
内心崩溃。。。但是为什么png不被压缩呢,我得找找为什么,看看代码实现。
if (canvas.toBlob) {
canvas.toBlob(done, options.mimeType, options.quality);
} else {
done(toBlob(canvas.toDataURL(options.mimeType, options.quality)));
}
canvas.toBlob:www.canvasapi.cn/HTMLCanvasE…
- toBlob()方法可以Canvas图像对应的Blob对象(binary large object)。此方法可以把Canvas图像缓存在磁盘上,或者存储在内存中,这个往往由浏览器决定。
- 语法 void canvas.toBlob(callback, mimeType, quality);
- 这里的void表示无返回值。 参数说明:
- toBlob()方法执行成功后的回调方法,支持一个参数,表示当前转换的Blob对象。
- mimeType(可选)String mimeType表示需要转换的图像的mimeType类型。默认值是image/png,还可以是image/jpeg,甚至image/webp(前提浏览器支持)等。
- quality(可选)Number quality表示转换的图片质量。范围是0到1。由于Canvas的toBlob()方法转PNG是无损的,因此,此参数默认是没有效的,除非,指定图片mimeType是image/jpeg或者image/webp,此时默认压缩值是0.92。
好吧,由于png是无损的,因此quality设置也是没有用的。。。我打断点跑了一下,图片压缩处理走的都是toBlob这个方法,不会执行到else上,所以png压缩基本没戏。。。那canvas.toDataURL是什么呢?
canvas.toDataURL:www.canvasapi.cn/HTMLCanvasE…
- 语法 canvas.toDataURL(mimeType, quality);
- 参数说明:
- mimeType(可选)String mimeType表示需要转换的图像的mimeType类型。默认值是image/png,还可以是image/jpeg,甚至image/webp(前提浏览器支持)等。
- quality(可选)Number quality表示转换的图片质量。范围是0到1。此参数要想有效,图片的mimeType需要是image/jpeg或者image/webp,其他mimeType值无效。默认压缩质量是0.92。 根据自己的肉眼分辨,如果使用toDataURL()的quality参数对图片进行压缩,同样的压缩百分比呈现效果要比Adobe Photoshop差一些。
- 返回值 返回base64 data图片数据。 toDataURL对性能要求比较高,canvas.toBlob兼容要求相对高一些。
此路不通罗马,条条大路通罗马,果断换一条。换到node端处理图片压缩。
使用imagemin:github.com/imagemin/im…
Install
$ npm install imagemin
$ npm install imagemin-jpegtran
$ npm install imagemin-pngquant
tips:发现打包的时候报错了,因为imagemin-pngquant默认安装8.0.0,改为5.0.1就好了。
核心代码:
// 图片压缩
const files = await imagemin([`${file.path}`], {
destination: 'template/images', // output
plugins: [
imageminJpegtran(),
imageminPngquant({
quality: [0.6, 0.8],
}),
],
});
fileContent = await fs.readFile(files[0].destinationPath);
fs.unlinkSync(files[0].destinationPath); // 删除压缩后的图片,防止文件越来越大
搞定!!!
有一疑问:质量压缩quality定义为0.5或0.6,是具体指压缩了多少呢。。。
写在最后:感谢对我帮助过的小伙伴,以及为大家作出贡献的大牛们,谢谢你们!文中如有错误,请帮忙指正,感谢!
ps:一个在前端路上努力的90后阿姨,微笑的人运气不会太差,前进的脚步可以放大。😁😁😁