必须用JS读取图片naturalWidth/naturalHeight校验分辨率,因HTML的accept/required属性无法限制;需用FileReader转data URL或URL.createObjectURL创建Image对象,等待onload后检查真实尺寸,并处理EXIF方向、Canvas绘制缩放及服务端二次校验。

用 JavaScript 读取图片原始尺寸再校验
HTML 的 accept 和 required 属性完全无法限制分辨率,必须靠 JS 在用户选图后主动读取并判断。核心逻辑是:用 FileReader 读取为 data URL → 创建 Image 对象 → 等待 load 回调 → 检查 img.naturalWidth 和 img.naturalHeight。
常见错误现象包括:
- 直接用
input.files[0].size判断——这是文件体积,和分辨率无关 - 用
img.width/img.height(CSS 渲染尺寸)代替naturalWidth/naturalHeight——会被缩放干扰,结果不准 - 没处理异步时序,在
img.onload外就访问尺寸——值为 0
实操建议:
- 最小宽高设为 295×413(证件照常用下限),或按业务定死如
minWidth = 800,minHeight = 600 - 校验失败时,清空
input.files并提示用户:“图片分辨率不足,请上传 ≥800×600 的图片” - 别在
change回调里直接return,要等Image加载完成再决定是否拦截提交
移动端拍照时前置控制分辨率,避免无效大图
用户用 capture="environment" 拍照,设备可能输出 4000×3000 像素的原始图,但你只要 800×600 ——与其上传后再校验失败,不如从源头压缩帧再读尺寸。
立即学习“前端免费学习笔记(深入)”;
关键点:
- 不依赖
getUserMedia直接拍全尺寸视频流,而是用input type="file" accept="image/jpeg" capture="environment"触发系统相机,并强制指定 MIME 类型,减少 iOS HEIC 或安卓 WebP 导致的解析失败 - 拿到
file后立即用URL.createObjectURL(file)创建临时地址,赋给Image;这样比FileReader.readAsDataURL更快、内存更省 - 某些安卓机型返回的
naturalWidth会因 EXIF orientation 错乱(比如 3000×4000 实际是横图但报成竖图),需配合exif-js解析Orientation字段,必要时交换宽高再比对
Canvas 绘制前再做一次尺寸兜底
即使校验通过,后续若要用 Canvas 压缩或裁剪,仍可能因宽高比拉伸导致内容变形。此时可在绘制前再次检查并修正。
例如证件照要求严格 295×413:
- 若原图
naturalWidth = 1200,naturalHeight = 1800,比例接近但不精确,直接 canvas 绘制会压缩失真 - 应先计算缩放比:
scale = Math.min(295 / naturalWidth, 413 / naturalHeight),再设置 canvas 尺寸为Math.round(naturalWidth * scale)×Math.round(naturalHeight * scale) - 如果缩放后仍小于 295×413(比如原图只有 500×300),说明宽高比严重偏离,应拒绝而非强行拉伸
容易踩的坑:
- canvas.width/canvas.height 必须用整数,且不能靠 CSS 缩放,否则
ctx.drawImage()输出模糊 - 调用
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)前,确保img已加载完成,否则 canvas 内容为空白
服务端仍需二次校验,前端限制只是体验优化
所有前端校验都可被绕过:用户禁用 JS、手动构造 FormData、用 Postman 上传任意图片。所以 min-resolution 必须在服务端重复验证。
实操建议:
- Node.js 可用
sharp库快速读取图片元信息:sharp(fileBuffer).metadata()返回{ width, height } - PHP 用
getimagesize($tmp_file),Python 用PIL.Image.open().size - 响应体返回明确错误码(如
422 Unprocessable Entity)和字段"field": "image", "message": "minimum resolution 295x413 required",方便前端精准提示
最易被忽略的是 EXIF 方向与实际像素方向不一致的问题——同一张照片在不同浏览器里 naturalWidth 可能互换,必须解析 orientation 后再判断真实宽高。这个步骤漏掉,会导致大量“明明够大却报错”的用户投诉。



















