图片上传前客户端自动压缩的核心是通过before-upload钩子拦截File对象,用compressorjs或Canvas在浏览器内降质缩放并返回压缩后的File,避免后端依赖,减小体积、节省带宽。

Vue 文件上传交互中,图片上传前的客户端自动压缩,核心是拦截原始文件、在浏览器内完成降质缩放、再把处理后的 Blob/File 传给上传逻辑。不依赖后端,压缩发生在用户本地,能显著减小上传体积、节省带宽、提升响应速度。
用 before-upload 拦截并压缩
Element Plus 的 el-upload 或 Ant Design Vue 的 a-upload 都支持 before-upload 钩子函数。它接收原始 File 对象,返回 false 可阻止上传,返回 Promise<file></file> 则会用该文件继续上传流程——这正是插入压缩逻辑的最佳位置。
- 判断是否为图片:检查
file.type.startsWith('image/') - 按大小分流:比如 ≤1MB 直接放过;>1MB 才触发压缩,避免小图画蛇添足
- 返回一个 Promise,在 resolve 中传入压缩后的 File 对象(不是 base64 字符串)
推荐使用 compressorjs 库(简洁可靠)
相比手写 Canvas,compressorjs 封装成熟、兼容性好、API 清晰,还自动处理 EXIF 朝向、支持 maxWidth/maxHeight 等维度控制。
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
- 安装:
npm install compressorjs - 调用示例:
beforeUpload(file) {
return new Promise((resolve, reject) => {
new Compressor(file, {
quality: 0.7,
maxWidth: 1200,
maxHeight: 1200,
success: (compressedFile) => resolve(compressedFile),
error: reject,
});
});
}
手写 Canvas 压缩(轻量无依赖)
若项目极简、不想引入新包,可用原生 Canvas 实现基础压缩。关键点在于:
立即学习“前端免费学习笔记(深入)”;
- 用
FileReader读取 file → 得到 dataURL - 创建
Image加载该 dataURL,确保 onload 后再绘图 - Canvas 宽高按比例缩放(如固定宽度 800px,高度等比),避免拉伸失真
- 调用
canvas.toBlob(callback, 'image/jpeg', 0.8)生成压缩后 Blob - 用
new File([blob], file.name, { type: 'image/jpeg' })转成标准 File 对象
注意几个实际细节
真实项目中容易踩坑的地方:
- EXIF 旋转问题:手机拍的照片常含 orientation 信息,Canvas 绘图默认不识别,会导致横图变竖。compressorjs 默认修复,手写需额外解析 EXIF 并手动旋转 canvas
-
类型保持:PNG 透明背景压缩成 JPEG 会丢透明通道,建议按原格式输出(
toBlob第二个参数动态传file.type) - 大图内存压力:超 5MB 图片在低端安卓机上可能卡顿,可加 size 限制或 fallback 到服务端压缩提示
-
上传组件适配:某些 UI 库(如早期 uView)的
http-request不接受 Blob,需转成 FormData 再发请求

















