js实现图片压缩
使用Canvas API压缩图片
Canvas的drawImage方法结合toDataURL可以调整图片尺寸和质量。创建一个新的Canvas元素,将图片绘制到指定尺寸后转换为Base64或Blob格式。
function compressImage(file, maxWidth, maxHeight, quality) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = function(e) {
const img = new Image();
img.onload = function() {
const canvas = document.createElement('canvas');
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.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, width, height);
canvas.toBlob(
(blob) => resolve(blob),
'image/jpeg',
quality
);
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
});
}
使用第三方库实现压缩
对于更复杂的压缩需求,可以考虑使用专门处理图片的库:
- compressorjs:提供丰富的压缩选项和回调处理
- browser-image-compression:支持Web Worker多线程压缩
安装compressorjs示例:

npm install compressorjs
使用示例:
import Compressor from 'compressorjs';
new Compressor(file, {
quality: 0.6,
maxWidth: 800,
success(result) {
const formData = new FormData();
formData.append('file', result, result.name);
// 上传处理后的文件
},
error(err) {
console.error(err.message);
},
});
调整输出格式优化压缩率
不同图片格式的压缩效果差异较大:

- JPEG:适合照片类图片,通过调整quality参数(0-1)控制质量
- WebP:现代格式,比JPEG节省25-35%体积
- PNG:适合需要透明度的图片,但体积较大
格式转换示例:
canvas.toBlob(
(blob) => {},
'image/webp', // 指定输出格式
0.7 // 质量参数
);
分片压缩大文件处理
对于超大图片文件,可采用分块读取处理的方式避免内存溢出:
const chunkSize = 1024 * 1024; // 1MB分块
let offset = 0;
while (offset < file.size) {
const chunk = file.slice(offset, offset + chunkSize);
// 对每个分块单独处理
offset += chunkSize;
}
上传前压缩完整流程
典型的前端图片压缩上传流程:
- 用户通过input选择图片文件
- 读取文件并创建Image对象
- 计算目标尺寸保持宽高比
- 使用Canvas重绘并导出压缩后数据
- 将结果转换为Blob或FormData
- 通过AJAX或Fetch API上传
document.getElementById('upload').addEventListener('change', async (e) => {
const file = e.target.files[0];
if (!file) return;
const compressedFile = await compressImage(file, 1024, 768, 0.7);
const formData = new FormData();
formData.append('image', compressedFile, 'compressed.jpg');
fetch('/upload', {
method: 'POST',
body: formData
}).then(response => {
// 处理服务器响应
});
});






