change事件是前端校验文件大小的唯一时机,需立即检查file.size并清空input值;应使用data-max-size属性动态配置阈值,后端须通过Nginx、框架、语言层三重限制确保安全。

change事件里检查file.size才是唯一可行的前端时机
用户选完文件后立刻校验,而不是等到submit——否则 2GB 视频已选中、点提交才弹错,体验崩坏。浏览器只在change触发时暴露files[0]和size属性,submit阶段拿不到原始文件对象。
常见错误现象:用input.addEventListener('submit', ...)试图拦截,结果e.target.files为空;或只判断files.length却漏掉file.size检查。
-
file.size单位是字节,5MB 必须写成5 * 1024 * 1024,别用5e6——可读性差,容易算错 - 旧版 Safari 或某些 WebView 可能返回
file.size === 0,加兜底:if (!file || !file.size) - 校验失败后必须执行
e.target.value = ''清空 input 值,否则重复选同名文件不会再次触发change
用data-max-size实现每个input独立配置
硬编码阈值(比如所有上传都限 5MB)会卡死后续需求:头像要 2MB,商品图要 10MB,PDF 合同要 50MB。HTML 层用自定义属性控制,JS 层读取并转数字,才能解耦。
示例写法:<input type="file" data-max-size="2097152">(2MB),JS 中用Number(input.getAttribute('data-max-size'))读取。
- 属性值是字符串,不显式转
Number()会导致'2097152' > 1000000按字典序比较,结果为false - 避免用
parseInt(str, 10)——虽然也能用,但Number()更直白且对空字符串返回NaN,便于统一判错 - 提示文案建议动态拼接:
文件不能超过 ${maxSize / 1024 / 1024}MB,别写死“5MB”
后端三重限制缺一不可:client_max_body_size、框架limits.fileSize、语言层upload_max_filesize
前端校验只是“友好提示”,curl、Postman、禁用 JS 都能绕过。真正拦住大文件,得靠后端三层硬闸门,漏一层就可能服务崩溃或静默失败。
- Nginx 层:
client_max_body_size 20M——设太小,请求连 Nginx 都进不去,直接 413,前端收不到任何响应 - 框架层:Node.js + multer 要配
limits: { fileSize: 10 * 1024 * 1024 },光校验req.file.size没用 - PHP 层:
upload_max_filesize和post_max_size都得调大,且后者必须 ≥ 前者,否则请求根本进不到 PHP
最容易被忽略的是 Nginx 和框架限制不一致:比如 Nginx 允许 20MB,multer 只允许 5MB,用户传 10MB 文件时,后端收不到数据,前端卡几秒后静默失败——你查 JS 日志、network 面板都找不到错,只会怀疑自己代码写错了。
accept属性对大小完全无效,别指望它
accept=".jpg,.png"只影响文件选择器默认过滤的类型列表,用户点“所有文件”就能绕过,且它根本不读取文件内容或尺寸。把它当辅助提示可以,当成限制手段就是自欺欺人。
真实场景中,有人传.jpg后缀但实际是 3GB 的视频容器,accept对此毫无反应。真正防这种,得靠后端读文件头(magic number)+ 限制size双校验。
如果业务真需要宽高限制(比如头像必须 200×200),那得用FileReader读取图片后用img.onload解析尺寸——这和size限制是两回事,别混在一起处理。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











