在上传图片之前,对图片进行压缩。看到这里是不是有点懵,前端怎么压缩图片呢,这不应该是后端做的吗?
但是我在开发的时候接到了这样一个需求,要求对用户上传的图片进行一定的压缩,而且并且尽量还原图片的清晰度。
那么对图片上传进行一个压缩的好处在哪里
- 提升用户体验:
- 减少图片加载时间,加快页面渲染速度。
- 对于移动设备来说尤为重要,可以减少流量消耗。
- 节省服务器资源:
- 减小上传文件的大小,降低服务器存储成本。
- 减轻服务器处理图片的压力。
- 优化网络传输:
- 在带宽有限的情况下,压缩后的图片可以更快地传输到服务器端。
坏处呢
显而易见,加大工作量,当然,图片也有可能会变得比较模糊(这也是我们要处理的)
本来开发没有引入任何的库,纯手写
使用技术栈为Vue3+Ts+Canvas
再开始之前需要了解部分前置知识,关于图片压缩的类型,压缩时我们会把图片的类型修改为**“image/jpeg”**,为什么呢?
JPEG(Joint Photographic Experts Group)是一种广泛使用的有损压缩图像格式,适用于照片和其他具有丰富色彩和细节的图像。JPEG 格式的主要优点是它能够提供高质量的图像同时保持较小的文件大小,这对于网络传输和存储来说是非常重要的。
兼容性:JPEG 格式在大多数浏览器和设备上都得到了很好的支持。
文件大小:JPEG 可以通过调整质量因子来控制输出文件的大小,这使得它非常适合在网络上传输。
颜色和细节:对于包含大量颜色和细节的照片来说,JPEG 通常能够提供足够的视觉质量。
质量参数:quality 参数只对某些格式有效,如 JPEG。这里使用 "image/jpeg" 可以确保 quality 参数被正确应用。
接下来就开始我们的编码,具体注释,案例,实现都在代码中有所解释
页面,引入的arco-design组件库的上传组件
<template>
<div>
<a-upload
:auto-upload="false"
ref="uploadRef"
@change="fileChange"
multiple
draggable
>
</a-upload>
</div>
</template>
逻辑
<script setup lang="ts">
let fileNum = 0;
const fileChange = async (files) => {
let file = files[fileNum].file;
console.log(file, "压缩之前");
// 用户还可能传其他的,只压缩图片,并且太小的图片都不进行处理
if (file.type.includes("image") && file.size >= 102400) {
file = await imageZip(file, 800, 600, 0.8);
}
console.log(file, "压缩之后");
//这里书写你的上传逻辑,根据自身的接口来上传
};
const imageZip = (file: File, maxWidth: number,maxHeight: number,quality: number) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
// 使用readAsDataURL方法十分适合用来读取图片文件,并将其转换为Base64编码的Data URL格式。
reader.readAsDataURL(file);
// 此时再使用reader.onload事件处理器,对图片进行处理
reader.onload = function (event) {
const img = new Image();
// 将base64的值赋值给img以便后续处理
img.src = event.target.result;
img.onload = function () {
let width = img.width;
let height = img.height;
// 这里是对图片做宽高自适应
if (width > maxWidth) {
height *= maxWidth / width;
width = maxWidth;
}
if (height > maxHeight) {
width *= maxHeight / height;
height = maxHeight;
}
// 创建一个Canvas
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
/**
img: 要绘制的 Image 对象。
0: 目标位置的 x 坐标。
0: 目标位置的 y 坐标。
width: 绘制的宽度。
height: 绘制的高度。
*/
ctx.drawImage(img, 0, 0, width, height);
// 直接使用canvas.toBlob()来创建压缩后的Blob对象
//
canvas.toBlob(
(blob) => {
const files = new File([blob], file.name, { type: file.type });
resolve(files);
},
//指定类型,原因前面也解释了
"image/jpeg",
// 控制质量,越小图片体积就越小,当然也会更加模糊
quality
);
};
};
});
};
</script>
我专门写了一个后台,来看图片的体积变化,总结:越大的图片压缩后,体积变化越大,同时后台查看图片也没有丢失精度