accept 不管后缀名,只控制文件选择框的大类;exts 才负责后缀字符串校验,但仅做上传前简单比对,不读文件内容也不影响弹窗显示。
accept 和 exts 到底谁在管后缀名显示
accept 不管后缀,只管系统文件选择框的大类(images/file/video),它本身不识别 .pdf 或 .zip;真正让 windows/macos 弹窗里“只看到 pdf”的,是 acceptmime。但 acceptmime 必须写标准值,比如 application/pdf,写成 file/pdf 或 pdf 就失效。
exts 才是唯一负责后缀字符串校验的参数,但它只做上传前的简单比对:取 file.name 最后一个点之后的部分,转小写,再看是否匹配你写的 jpg|png|gif。它不读文件内容,也不影响弹窗——用户照样能选中 hack.exe 并改名为 report.pdf 绕过 exts。
- 想让弹窗只显示 PDF 文件:必须设
accept: 'file'+acceptMime: 'application/pdf' - 想前端拦住非 JPG/PNG:设
exts: 'jpg|png',但仅此一项无法阻止用户选中config.txt - 多后缀必须用竖线分隔:
exts: 'xls|xlsx|csv'✅,exts: 'xls, xlsx'❌
size 单位是 KB,不是 MB
size 参数单位固定为 KB,这是最容易翻车的地方。写 size: 2048 是 2MB,size: 5120 才是 5MB。如果误写 size: 5,实际只允许 5KB 的文件——一张稍大的截图都传不过去。
超限文件在 choose 回调里根本不会出现:obj.getChooseFiles() 返回的列表里已经过滤掉了;before 回调也不会触发。错误提示靠 text["limit-size"] 自定义,不设就弹默认文案 “文件大小不能超过 XX KB”。
- 服务端必须重复校验,前端限制可被完全绕过
-
size限制的是单个文件,不是多选时的总和 - 哪怕只传一个超限文件,整个批次都会被拦在
choose阶段外
黑名单文件名只能在 before 里手动拦截
Layui 没有内置黑名单机制。exts 是白名单,只认后缀;要拦 config.js、.env、Thumbs.db 这类特定文件名,唯一可靠位置是 before 回调。
别在 choose 里写校验逻辑——它的返回值被忽略;也别直接改 upload.js 源码,维护成本高且易出错。
- 用
Array.from(obj.getChooseFiles())获取真数组,避免obj.files可能为空 - 比对前统一转小写:
f.name.toLowerCase(),兼顾大小写敏感场景 - 用
some()判断是否存在命中项,命中就return false阻断整批上传 - 提示信息要具体:
layer.msg(`禁止上传:${blocked.map(f => f.name).join('、')}`)
acceptMime 的兼容性坑比想象中深
acceptMime 看似精准,但浏览器实现差异大。Safari 对 image/webp 支持不稳定,得补上 image/x-webp;旧版 Edge 可能忽略 application/x-rar-compressed,换成通用型 application/octet-stream 又失去精度。
更麻烦的是 MIME 类型必须严格标准:application/zip ✅,file/zip ❌,zip ❌,application/x-zip-compressed 在部分安卓 WebView 里也不认。
- 上线前务必在目标环境(尤其 iOS Safari)实测弹窗是否真过滤
- 不要只依赖
acceptMime,exts+before中的file.type检查是必要补充 -
file.type由浏览器推测,不可全信,但比exts的字符串匹配强得多
acceptMime 控制弹窗可见性,exts 做后缀初筛,size 拦大文件,before 里才是你最后能动手脚的地方。而所有这些,都只是客户端体验层的“提醒”,真正的防线永远在服务端。











