input[type="file"]无法限制像素尺寸,accept仅过滤类型,size只校验字节数;必须用FileReader+Image读取Data URL后在onload中检查img.width。

input[type="file"] 本身不提供像素级尺寸限制能力,必须用 JavaScript 读取图片原始宽高做校验——否则用户上传一张 8000×6000 的图,后端再拦就晚了。
为什么 accept 和 size 属性拦不住像素尺寸
accept 只过滤文件扩展名或 MIME 类型,size(即 files[0].size)只检查字节数。一张重度压缩的 12MP 图片可能才 2MB,但原始像素是 4000×3000,远超你期望的「最大宽度 1920」。浏览器不暴露像素信息直到你用 FileReader + Image 加载它。
用 FileReader + Image 获取原始宽度并判断
核心逻辑是:选中文件 → 读取为 Data URL → 创建 Image 实例 → 等待 onload → 检查 image.width。
关键点:
立即学习“前端免费学习笔记(深入)”;
- 必须等
image.onload触发后才能读取width,否则是 0 - 不能用
image.naturalWidth替代image.width,两者在此场景下值相同,但width更直白、兼容性无差别 - 若用户取消选择或文件非图片,
file.type不以image/开头,可提前 return 避免报错 - 示例中限制最大宽度为 1920:
function checkImageMaxWidth(file, maxWidth = 1920) {
if (!file || !file.type.startsWith('image/')) return false;
<p>const reader = new FileReader();
reader.onload = function(e) {
const img = new Image();
img.onload = function() {
if (img.width > maxWidth) {
alert(<code>图片宽度 ${img.width}px 超出限制(最大 ${maxWidth}px)</code>);
file.parentElement.querySelector('input[type="file"]').value = '';
}
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
}绑定到 input onchange 时的常见坑
直接在 onchange 里调用会出问题,因为 file.files[0] 才是真正的 File 对象,this 是 input 元素本身。
正确写法要点:
- 事件监听要取
event.target.files[0],不是event.target.value - 别在
onchange里直接用this.files[0]—— 某些旧版 Safari 下可能为空,稳妥起见加判空 - 多个文件上传时,需遍历
files列表逐个校验,不能只看第一个 - 如果页面有多个上传控件,建议把
maxWidth提到data-max-width属性里动态读取,避免硬编码
要不要同时限制高度或宽高比
纯宽度限制够用,但实际业务常需组合判断。比如要求「宽度 ≤ 1920 且高度 ≤ 1080」,或「必须是 16:9,误差±2%」。这时候不要用 img.width / img.height === 16 / 9 直接比较(浮点误差),改用差值绝对值判断:
const ratio = img.width / img.height;
if (Math.abs(ratio - 16/9) > 0.02) { /* 不符合 */ }更复杂规则(如最小像素、裁剪区域)就得上 canvas 采样或服务端校验了——前端只做快速初筛,别让它承担最终判定责任。



















