HTML原生不支持文件夹上传,webkitdirectory是Chromium专属实验性属性,需同时满足type="file"、无multiple、显式声明webkitdirectory和directory,且用户须手动进入文件夹选择;其返回的FileList扁平化,路径信息仅存于file.webkitRelativePath,需前端主动通过FormData.append()传递,后端解析并防护路径穿越;Firefox/Safari不支持,跨浏览器方案只有拖拽(仍限Chromium)或JSZip打包上传。

HTML 原生不支持「选择文件夹并上传其全部内容」——input[type="file"] 默认只能选文件,不能选目录。所谓“文件夹上传”,实际是浏览器对 webkitdirectory 属性的非标准扩展支持,且仅限部分 Chromium 内核浏览器(Chrome、Edge)有效,Firefox 和 Safari 完全不支持。
为什么 input 加了 webkitdirectory 还没反应?
这个属性是实验性特性,必须同时满足三个条件才生效:
-
input必须有type="file"且不能带multiple(加了反而会禁用目录模式) - 必须显式声明
webkitdirectory和directory(后者是草案标准,但目前无实际作用,仅作兼容写法) - 用户必须在弹出的选择对话框中**手动点击进入某个文件夹再点“确定”**,而不是直接选中文件夹图标(很多用户卡在这一步)
正确写法示例:
<input type="file" webkitdirectory directory>
注意:此时 e.target.files 返回的是一个扁平化的 FileList,包含该文件夹下所有文件(含子目录中的),但**不保留目录结构路径**——所有文件的 file.webkitRelativePath 字段才记录原始相对路径,比如 "docs/report.pdf" 或 "images/logo.png"。
webkitRelativePath 怎么用?后端能靠它还原目录吗?
可以,但得前端主动传、后端主动解析。浏览器不会自动把路径信息塞进 multipart 字段名里,你得自己用 FormData.append() 把路径作为额外字段带上:
const input = document.querySelector('input[type="file"][webkitdirectory]');<br>input.addEventListener('change', e => {<br> const files = e.target.files;<br> const formData = new FormData();<br> for (let i = 0; i const file = files[i];<br> // 关键:用 webkitRelativePath 构造唯一 key<br> const key = `files[${file.webkitRelativePath}]`;<br> formData.append(key, file);<br> }<br> fetch('/upload', { method: 'POST', body: formData });<br>});
后端收到的字段名就带路径了(如 files[assets/js/main.js]),但要注意:webkitRelativePath 在非 Chromium 浏览器里是空字符串,无法 fallback;且它的值不受控——用户可手动修改路径名,不能用于权限校验或路径遍历防护。
有没有真正跨浏览器的文件夹上传方案?
没有原生方案。可行替代路径只有两个:
- 用
input[type="file"][multiple]+ 手动拖拽整个文件夹到页面(监听drop事件),再递归读取DataTransferItem.webkitGetAsEntry()(同样仅 Chromium 支持) - 放弃“选文件夹”交互,改用前端 ZIP 库(如
JSZip)让用户先选多个文件,再打包成 zip 后上传——路径信息可由 JS 完全控制,100% 跨浏览器,但体验稍重
如果你的应用必须支持 Firefox/Safari,又需要目录结构,就只能走 ZIP 路线。别指望 webkitdirectory 能兜底——它连 iOS Safari 都不认,更别说安全策略收紧后未来可能被移除。
最易被忽略的一点:即使浏览器返回了 webkitRelativePath,服务端接收到的仍是扁平文件流,路径只是个字符串字段;你得自己按斜杠拆分、创建嵌套目录、防止 ../ 路径穿越——这部分逻辑完全不在前端控制范围内,必须后端严防死守。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











