webkitdirectory 不支持 accept 过滤,需手动遍历 FileList 校验扩展名、类型和大小;iOS Safari 不支持该属性;服务端必须用 magic bytes 重校文件真实类型并设多重体积限制。

webkitdirectory 属性本身不支持 accept 过滤
直接给 加 accept 属性是无效的——浏览器会忽略它。这是规范限制,不是写法错误。目录选择模式下,accept 完全不起作用,连 UI 提示都不会生效。
原因在于:webkitdirectory 触发的是文件夹遍历,系统返回的是整个目录结构(FileList 中每个 File 对象代表一个文件),而 accept 只在单文件选择对话框中参与过滤逻辑。
- 你不能靠
accept=".pdf,.png"让用户只看到 PDF 和 PNG 文件夹里的内容 -
capture、multiple等属性在目录模式下也基本失效或行为未定义 - 目前没有标准属性能“预筛”文件夹内文件类型,所有筛选必须后置
前端校验必须遍历 FileList 并逐个检查
用户选中一个文件夹后,event.target.files 是一个包含所有子文件(不含子目录)的 FileList。你需要手动遍历并校验每一项,不能只看第一个。
- 用
Array.from(event.target.files)转成数组,避免for...in误读原型方法 - 对每个
file,同时检查:file.name扩展名(大小写不敏感)、file.type(仅作参考)、file.size(防超大单文件) - 扩展名提取要严谨:
const ext = file.name.split('.').pop().toLowerCase(),避免"archive.tar.gz"被误判为"gz" - 发现非法文件时,明确记录文件名并提示,比如
"跳过 2 个不支持的文件:script.js、config.json" - 校验失败后清空 input:
inputEl.value = '',否则下次 change 不触发
移动端 Safari 不支持 webkitdirectory
iOS Safari 完全不识别 webkitdirectory,点击后只会打开普通单文件选择器,且不支持多选。这不是兼容性问题,是功能缺失。
- Android Chrome、Edge(桌面/安卓)、新版 macOS Safari 支持该属性
- 若需跨平台支持文件夹上传,必须降级为多文件选择(
multiple)+ 明确引导用户按住 Ctrl/Cmd 多选 - 无法通过 JS 检测 “是否支持目录选择”,只能 UA 判断或尝试后 fallback;但 UA 检测不可靠,建议用
if ('webkitdirectory' in document.createElement('input'))做特性检测
后端必须重做全部校验逻辑
前端对文件夹内文件的任何过滤都可被绕过:禁用 JS、修改 DOM、直接 POST 构造请求。服务端收到的仍是原始 multipart/form-data 流,每一份文件都得独立校验。
- 不能信任
req.file.originalname或Content-Type请求头——它们由前端控制 必须读取每个文件的前若干字节(magic bytes)判断真实类型: - PHP 用
finfo_file($finfo, $tmpFile);Node.js 推荐file-type包;Python 用python-magic或libmagic - 别漏掉大小限制:单文件超限、总文件数超限、总上传体积超限,三者都要在服务端设阈值
%PDF、\x89PNG、\xFF\xD8\xFF 等
真正难的不是怎么写 webkitdirectory,而是意识到它只解决“选文件夹”这一步,后面从遍历、过滤、提示到服务端落地,全是手工活,且一环都不能少。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











