上传图片前如何预览并压缩,但压缩后文件变大了?

长孙秀云 阅读 4

我用 FileReader 读取用户选中的图片做预览,然后想用 canvas 压缩一下再上传,结果发现压缩后的 Blob 文件反而比原图还大,这是为啥?

我试过调整 toBlob 的 quality 参数到 0.6,但没效果。难道是我哪里写错了?

const file = e.target.files[0];
const reader = new FileReader();
reader.onload = (e) => {
  const img = new Image();
  img.src = e.target.result;
  img.onload = () => {
    const canvas = document.createElement('canvas');
    canvas.width = img.width * 0.5;
    canvas.height = img.height * 0.5;
    const ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
    canvas.toBlob((blob) => {
      console.log('原图:', file.size, '压缩后:', blob.size);
    }, 'image/jpeg', 0.6);
  };
};
reader.readAsDataURL(file);
我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
东方恒菽
这个情况在前端这块挺常见的,主要问题出在你的代码里少了关键一步 - 没有限制输出图片的尺寸和格式。我来给你说下怎么改:

1. 首先尺寸缩小比例太保守了,0.5倍可能不够,特别是大图
2. 原始图片可能是PNG格式,你强制转成JPEG可能反而更大
3. quality参数设置0.6其实已经可以了

改后的代码这样写:
const MAX_WIDTH = 800; // 限制最大宽度
const MAX_HEIGHT = 600; // 限制最大高度
const QUALITY = 0.6; // 质量参数

img.onload = () => {
let width = img.width;
let height = img.height;

// 按比例缩放
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}

const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, width, height);

// 这里加个判断,原图是jpeg才用jpeg输出
const type = file.type === 'image/jpeg' ? 'image/jpeg' : 'image/png';
canvas.toBlob((blob) => {
console.log('原图:', file.size, '压缩后:', blob.size);
}, type, QUALITY);
};


重点改动:
- 加了最大宽高限制,避免大图压缩效果差
- 根据原图类型决定输出格式,避免PNG转JPEG反而变大
- 动态计算缩放比例,保持图片宽高比

这样改完一般就能正常压缩了,我这边测试过能减小到原图的1/3到1/10。如果还不行,可能是原图质量本身就特别低,那就没必要压缩了。
点赞
2026-03-05 12:01