Appearance
图片压缩
在前端开发中,图片压缩是一个常见的需求。通过在客户端压缩图片,可以显著减少上传流量,加快上传速度,并减轻服务器的存储和带宽压力。
本文介绍两种实现方案:
- 使用成熟的第三方库
Compressor.js(推荐)。 - 使用原生 JavaScript (
Canvas API) 手动实现。
方案一:使用 Compressor.js 库 (推荐)
Compressor.js 是一个轻量级的 JavaScript 图像压缩库,它使用浏览器的原生 canvas.toBlob API 进行压缩。
核心优势:自动处理了最棘手的 EXIF 方向 (Orientation) 问题(即手机拍摄的照片在 Canvas 中可能会倒置),并且 API 简洁易用。
在线演示
核心代码
javascript
import Compressor from 'compressorjs';
new Compressor(file, {
quality: 0.8,
maxWidth: 1920,
maxHeight: 1080,
mimeType: 'image/jpeg',
success(result) {
// result 是一个压缩后的 Blob 对象
const formData = new FormData();
formData.append('file', result, result.name);
// 上传 formData...
},
error(err) {
console.log(err.message);
},
});方案二:原生 JS 实现
如果你不想引入额外的依赖,或者只需处理简单的场景(不需要考虑 EXIF 旋转),可以使用原生的 Canvas API 来实现。
注意:下面的演示没有处理 EXIF 方向信息。如果你上传一张由手机竖屏拍摄的照片,可能会发现压缩后的预览图是横向倒置的,这就是原生实现最主要的坑。
在线演示
核心实现原理
- 使用
FileReader读取文件为 DataURL。 - 创建
Image对象加载图片。 - 创建
<canvas>,根据最大宽/高计算缩放后的尺寸。 - 使用
ctx.drawImage()将图片绘制到 Canvas 上。 - 使用
canvas.toBlob()导出压缩后的 Blob 对象。
javascript
const compressImageNative = (file, quality = 0.8) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (event) => {
const img = new Image();
img.src = event.target.result;
img.onload = () => {
// 1. 计算目标尺寸
const maxWidth = 1920;
let width = img.width;
let height = img.height;
if (width > maxWidth) {
height = Math.round(height * (maxWidth / width));
width = maxWidth;
}
// 2. 创建 Canvas
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
// 3. 绘制图片 (注意:未处理 EXIF 旋转)
ctx.drawImage(img, 0, 0, width, height);
// 4. 导出压缩后的 Blob
canvas.toBlob(
(blob) => {
console.log('压缩完成', blob);
},
'image/jpeg',
quality
);
};
};
};方案对比
| 特性 | Compressor.js (库) | 原生 JS (Canvas) |
|---|---|---|
| 实现难度 | ⭐ (极低,API 简单) | ⭐⭐⭐ (需处理异步链、尺寸计算) |
| EXIF 旋转 | ✅ 自动处理 (内置逻辑读取并修正) | ❌ 需手动处理 (非常繁琐,需解析二进制数据) |
| 包体积 | ~6KB (Gzipped) | 0KB (无依赖) |
| 功能丰富度 | 高 (支持尺寸限制、类型转换、质量控制等) | 低 (需全部自行编写算法) |
| 兼容性 | ✅ 处理了 iOS Safari 大图限制等坑 | ⚠️ 需自行处理各浏览器怪异行为 |
| 适用场景 | 生产环境、移动端上传、对稳定性有要求 | 极简单的后台管理工具、学习研究 |
总结:在生产环境中,强烈建议使用 Compressor.js 或类似的成熟库,因为手动处理 EXIF 方向信息(Orientation)和各种浏览器的 Canvas 兼容性问题(如 iOS Safari 的 Canvas 内存限制)是非常耗时且容易出错的。