html5 file输入框不校验文件大小,必须用js在change事件中读取files[0].size判断并清空input值,否则重复选择同名超限文件不触发事件;前端校验是用户体验止损点,后端仍需重复校验。

HTML5 input[type="file"] 本身不校验文件大小
浏览器不会主动拦截超限文件上传,accept 属性只管类型,不管大小;max、min 对 file 类型无效。所谓“限制”,必须靠 JS 主动读取 files[0].size 判断,否则用户选中大文件后,上传请求照发,后端才会报错。
常见错误现象:
– 页面没提示,用户点了上传才看到 413 或后端返回的“文件太大”
– 用 input 的 required 或正则骗自己以为“已控制”
- 校验必须在
change事件里做,不能等表单提交时才查 - 要检查
event.target.files.length > 0,避免空选择时读files[0]报undefined - 单位是字节(bytes),别把 MB 当 KB 用 —— 2MB = 2 * 1024 * 1024 =
2097152
用 File.size 做前端即时校验的写法
这是最轻量、兼容性最好(IE10+)的方式,不依赖任何库,也不触发实际读取文件内容。
document.getElementById('upload').addEventListener('change', function (e) {
const file = e.target.files[0];
if (!file) return;
const maxSize = 2 * 1024 * 1024; // 2MB
if (file.size > maxSize) {
alert(`文件不能超过 2MB,当前:${(file.size / 1024 / 1024).toFixed(2)}MB`);
e.target.value = ''; // 清空 input,否则同名文件再次选中不会触发 change
}
});- 务必清空
e.target.value,否则用户选同一个超限文件两次,第二次不会触发change事件 - 不要用
console.log替代用户提示,没人盯着控制台 - 移动端 Safari 对大文件的
size读取是同步且可靠的,不用额外 try/catch
为什么不能只靠后端校验,还非得前端拦
不是为了“炫技”,是真实成本问题:用户上传 500MB 视频,等两分钟才被告知失败,带宽、服务器连接、CDN 中转、日志堆积全白耗。尤其弱网环境下,卡在 pending 状态比报错更让人困惑。
立即学习“前端免费学习笔记(深入)”;
- 前端校验是用户体验止损点,不是安全防线 —— 后端仍必须重复校验
- 某些 CDN 或反向代理(如 Nginx)默认 1MB 请求体上限,未配
client_max_body_size就直接 413,连后端都收不到请求 - 如果上传走的是
fetch或XMLHttpRequest,超限后只能靠catch捕获网络层错误,无法区分是超限还是断网
Chrome/Firefox/Safari 对超限文件的 UI 差异
浏览器不会统一禁用超限文件选择,但行为有差别:
- Chrome 和 Firefox:允许选,前端 JS 可正常读
size,无隐藏限制 - Safari(macOS/iOS):对单个文件 > 4GB 可能静默截断或抛
NotFoundError,但files[0].size仍可读(只是不准) - 所有浏览器:如果
input设了multiple,要遍历每个files[i],不能只看第一个
真正容易被忽略的点:服务端接收路径(比如 /api/upload)可能被 Nginx 或云函数设了全局 body 限制,和前端 JS 校验的值对不上 —— 前端提示 2MB,结果 Nginx 在 1MB 就切掉了,用户看到的错误既不是前端提示,也不是后端返回,而是空白响应或 CORS 失败。











