JavaScript 必须用 URL.createObjectURL() 创建临时 URL 并通过 Image 对象的 onload 事件读取 naturalWidth/naturalHeight 才能准确校验图片尺寸,需处理 onerror、及时 revokeObjectURL,并以服务端校验为最终防线。

用 JavaScript 读取文件尺寸做前端校验
HTML 表单本身不支持对上传图片的长宽做原生校验,<input type="file"> 只能限制类型和大小(通过 accept 和 max-size 属性),但无法判断像素尺寸。必须靠 JavaScript 读取文件元数据或解码图像后获取真实 width / height。
关键点在于:不能只依赖 File 对象的 name 或 size,得用 URL.createObjectURL() 创建临时 URL,再用 Image 对象加载并监听 load 事件——只有这时才能安全读取 img.naturalWidth 和 img.naturalHeight。
常见错误是直接在 change 回调里同步读取尺寸,结果拿到的是 0;或者没处理 Image 加载失败(比如损坏图、跨域资源),导致校验逻辑静默跳过。
- 必须等
img.onload触发后才读取naturalWidth/naturalHeight - 务必添加
img.onerror处理,否则损坏图会卡在校验环节且无提示 - 校验完记得调用
URL.revokeObjectURL(url)避免内存泄漏 - 若需支持多图上传,每个文件都要单独创建
Image实例,不可复用
校验逻辑写在哪:表单提交前还是文件选择后?
两种时机各有适用场景:选中后立刻校验(input[type="file"].onchange)适合强约束,比如头像上传要求必须是 1:1 正方形;而提交时校验(form.onsubmit)更灵活,可配合其他字段统一验证,也方便用户批量修改。
立即学习“前端免费学习笔记(深入)”;
性能上差异不大,但体验上要注意:如果在 change 时弹出警告,用户可能还没填完其他必填项就看到报错,显得突兀;而提交时校验,可以汇总所有问题(如“图片尺寸不符”+“邮箱格式错误”)一并提示。
- 头像/Logo 等强规格场景 → 推荐
change后立即校验 + 清空input.value并提示 - 普通内容发布表单 → 推荐
submit事件中异步校验,失败时event.preventDefault() - 校验过程应加 loading 状态(如禁用提交按钮),避免重复点击触发多次
Image加载
最小/最大尺寸怎么比:用自然尺寸还是显示尺寸?
必须用 img.naturalWidth 和 img.naturalHeight,它们反映原始像素值;img.width / img.height 是 CSS 渲染尺寸,受样式影响,完全不可靠。
注意:某些图片带 EXIF 方向信息(如手机竖拍图),浏览器自动旋转显示,但 naturalWidth/naturalHeight 不会自动交换——也就是说,一张实际是 720×1280 的竖图,其 naturalWidth === 720,naturalHeight === 1280,即使它在页面上被 CSS 旋转了 90° 显示为“横图”。校验逻辑无需手动处理方向,除非业务明确要求“显示为横图时宽必须大于高”。
- 校验最小宽度:用
img.naturalWidth < 300,不是img.width < 300 - 校验比例(如 16:9):计算
img.naturalWidth / img.naturalHeight,容忍浮点误差(建议用Math.abs(ratio - 16/9) < 0.01) - 不推荐用
FileReader.readAsDataURL()解析 base64 再创建Image,效率低且大图易卡顿;createObjectURL更轻量
兼容性与降级:老浏览器或特殊格式怎么办?
IE10+、Edge 12+、Chrome 13+、Firefox 10+ 都支持 createObjectURL 和 Image.naturalWidth;Safari 6.1+ 也支持。真正的问题不在浏览器,而在图片格式本身:WebP、AVIF 在旧版 Safari 中可能无法正确解析 naturalWidth,返回 0;HEIC(iPhone 默认)则根本不会被 accept="image/*" 匹配,需显式加 accept=".heic,image/*"(但依然无法保证尺寸读取成功)。
所以不能把前端校验当唯一防线。服务端必须重新解码图片并校验尺寸——前端只是提升体验,减少无效请求。
- 遇到
naturalWidth === 0,优先检查是否是 WebP/AVIF/HEIC 等格式,再 fallback 到服务端校验提示 - 移动端 iOS 上传 HEIC 文件时,
File.type可能为空字符串,别只靠 MIME 类型过滤 - 如果业务允许,可在后端返回校验失败时附带具体尺寸(如
{"error": "too_small", "required_min_width": 800, "actual_width": 640}),让前端展示更精准的提示
校验图片尺寸这件事,表面看只是读两个属性,实际牵扯到文件生命周期、图像解码时机、格式兼容边界和服务端兜底责任——最容易被忽略的,是以为前端拿到 naturalWidth 就万事大吉,却没处理加载失败或格式不支持的情况。



















