size、accept、exts、acceptmime 必须同时配置才有效:size 控制单文件体积(字节),accept 影响原生选择框初始筛选,exts 做后缀字符串匹配,acceptmime 真正控制 input 的 accept 属性;choose 回调中才能获取真实 file.size,before 中 files 为 undefined;多文件需用 array.from 遍历并逐个校验;before 支持 promise 用于异步校验;前端限制可被绕过,服务端必须校验文件头、真实 mime、后缀及大小。

size 和 accept/exts/acceptMime 必须同时配齐才有效
只设 size: 2048,用户仍能选中超限文件——它只在底层过滤,不阻止选择框弹出;只设 accept: "image",只是让系统文件对话框默认筛选图片类,但用户点“所有文件”就能绕过;只写 exts: "jpg|png",后缀校验发生在 choose 阶段,此前无法拦截。三者缺一不可:size 控单文件 KB 级体积,accept 影响原生选择框初始分类,exts 做文件名后缀字符串匹配,acceptMime 才真正控制 <input type="file"> 的 accept 属性。推荐组合:accept: "file"(显式放开选择范围)+ exts: "jpg|png|gif" + acceptMime: "image/jpeg,image/png,image/gif"。
choose 回调里才能拿到真实 file.size,before 里没有 files
很多人误在 before 回调里读 obj.file.size 或 obj.elem.files[0].size,结果是 undefined 或 0。Layui 在 before 阶段已剥离原始 FileList,只保留上传上下文。真正能读到字节大小的唯一时机是 choose 回调里的 obj.files[0].size(单文件)或遍历 obj.files(多文件)。注意单位是字节,换算 KB 要除以 1024,不是 1000。
- 超限判断示例:
if (file.size > 5 * 1024 * 1024) { layer.msg('文件不能超过 5MB'); return; } - 多文件需逐个检查:
Array.from(obj.files).forEach(file => { ... }),别用 for-in 遍历obj.files(它是 FileList,非数组) - 校验失败时调用
obj.clear()清空已选,避免用户误以为还能传
before 回调支持 Promise,适合做异步权限或服务端预检
如果校验逻辑依赖后端(比如检查用户剩余上传配额、文件名是否已存在),before 是唯一支持异步的钩子。返回 Promise 即可:resolve 继续上传,reject 中断并触发 error 回调。注意不要在 before 里尝试读文件内容或计算 MD5——此时已无 files,必须把这类操作提前到 choose 阶段做完并缓存结果。
- 正确写法:
before: function(obj) { return $.get('/api/upload/check', { size: obj.files[0].size }).then(res => { if (!res.ok) throw '配额不足'; }); } - 错误写法:
before: function(obj) { console.log(obj.files); }(此处obj.files为undefined) - reject 后不会触发
done,但会进error,记得配好该回调处理提示
前端限制只是第一道筛子,服务端校验不可省
size 和 exts 全部可被浏览器开发者工具绕过:改 DOM 的 accept 属性、删掉 onchange 监听、甚至直接 fetch 提交。所以服务端必须重新校验文件头(Magic Number)、真实 MIME、完整后缀、实际字节数。尤其注意:exts 不区分大小写,但服务端解析时若未转小写,.JPG 可能被拒;acceptMime 里写的 image/jpg 是错的,标准是 image/jpeg,服务端按 RFC 校验会失败。
最容易被忽略的是:拖拽上传时 acceptMime 完全失效(浏览器不支持),此时全靠 exts 和 choose 里的手动校验撑住——别假设用户只会点按钮选文件。











