H5前端压缩超大照片的核心是先降分辨率再控画质:按最长边≤1200px等比缩放Canvas,再用toDataURL('image/jpeg', 0.75)编码压缩,最后转Blob上传。

在 H5 中对超大照片(比如 5MB+ 的手机原图)做前端压缩再上传,核心是两步:先降分辨率(缩画布),再控画质(调 toDataURL 参数)。不依赖后端,全程浏览器内完成,能显著减小体积、节省流量、提升上传成功率。
关键压缩逻辑:两次压缩协同生效
单靠 toDataURL 的 quality 参数对超大图效果有限——它只压缩编码质量,不减少像素数。真正有效的做法是分两层压缩:
- 第一层:Canvas 尺寸压缩(降分辨率)——按最大宽高(如 1200px)等比缩放,大幅减少像素总量。这是体积下降的主力。
- 第二层:toDataURL 画质压缩(控编码)——设置 quality 在 0.6~0.8(即 60%~80%),在清晰度和体积间取得平衡。
完整流程与关键代码要点
从选图到生成可上传的 Blob,需严格按顺序执行:
- 用
<input type="file" accept="image/*">获取文件,优先过滤非图片类型和过大文件(如 >8MB 可直接提示)。 - 用
FileReader读取为 base64,赋给new Image()实例;监听onload确保图片加载完成后再操作。 - 读取
img.naturalWidth / naturalHeight得到真实尺寸,计算目标宽高(例如限制最长边 ≤ 1200px,保持宽高比)。 - 创建
canvas,设其width和height为目标尺寸;用ctx.drawImage(img, 0, 0, targetWidth, targetHeight)绘制缩放后图像。 - 调用
canvas.toDataURL('image/jpeg', 0.75)得到压缩后的 base64 字符串(PNG 格式慎用,体积通常更大)。 - 用工具函数将 base64 转为 Blob(注意 mime 类型匹配),并手动指定文件名(如
blob.name = 'photo.jpg')。
上传前必须做的几件事
压缩完不是终点,上传环节仍有细节决定成败:
立即学习“前端免费学习笔记(深入)”;
-
构造 FormData:把 Blob append 进
new FormData(),字段名需和服务端约定一致(如'file'或'image')。 -
设置请求头:不要手动设
Content-Type,让浏览器自动设置 boundary;否则 FormData 会出错。 - 加 loading 与错误兜底:超大图在低端安卓机上可能卡顿或内存溢出,建议加超时判断(如 5 秒未完成则提示“压缩失败,请重试”)。
-
保留原始信息可选:如需记录原图尺寸或 EXIF,可在压缩前用
exif-js提取,附在 FormData 中一同上传。
移动端特别注意事项
H5 在手机上运行环境更复杂,这些点容易踩坑:
- iOS Safari 对 canvas 尺寸有硬限制(通常 ≤ 4096×4096),超大图需先检查
naturalWidth * naturalHeight,超过则分步缩放(先缩一半,再绘入新 canvas)。 - 部分安卓 WebView(如旧版 UC)不支持
toDataURL('image/jpeg')的 quality 参数,降级方案:固定用toDataURL('image/jpeg')(默认约 0.92),再靠尺寸压缩扛住。 - 拍照直传场景建议加
capture="environment",避免用户误选相册里已压缩过的图,干扰压缩逻辑判断。


















