HTML不支持同步上传文件夹,webkitdirectory是WebKit/Blink私有属性,仅异步(fetch/XMLHttpRequest)可用,通过webkitRelativePath保留路径;Firefox及移动端不支持。

HTML 本身不支持直接上传文件夹(input type="file" 默认忽略目录结构),所谓“上传文件夹”实际是浏览器对 webkitdirectory 属性的支持,且仅限于异步方式;同步表单提交无法传递目录信息,强行设置 enctype="multipart/form-data" 也收不到子文件路径。
为什么 <input type="file" webkitdirectory> 只能异步用
该属性是 WebKit/Blink 内核私有扩展(Chrome、Edge、Safari 支持,Firefox 不支持),它让 event.target.files 返回包含子目录中所有文件的扁平化 FileList,但每个 File 对象的 webkitRelativePath 才保存原始路径。这个路径字段在表单同步提交时会被丢弃——服务器根本收不到。
所以必须用 JavaScript 读取 files 并手动构造请求体:
-
webkitRelativePath是只读字符串,例如"project/src/main.js",可用于服务端还原目录结构 - 同步提交的
form会把所有文件当平级处理,无法区分来源子目录 - 即使你用
FormData.append('file', file, file.webkitRelativePath),也只有异步请求(XMLHttpRequest或fetch)能真正把第三个参数作为文件名发送
fetch 上传带目录结构的文件列表
这是目前最简洁、可维护性最高的做法,fetch 原生支持 FormData,且能保留 webkitRelativePath 作为文件名。
立即学习“前端免费学习笔记(深入)”;
关键点:
- 必须监听
change事件,不能靠按钮 click 后再查input.files——用户可能已清空选择 - 遍历
event.target.files,对每个File调用formData.append('files', file, file.webkitRelativePath) - 后端需按多文件 + 文件名解析,不能只认
name字段 - 若某浏览器不支持
webkitRelativePath(如 Firefox),该字段为"",需降级为统一命名或报错提示
示例片段:
document.getElementById('folderInput').addEventListener('change', function(e) {
const formData = new FormData();
Array.from(e.target.files).forEach(file => {
// 保留原始路径,服务端可用它建目录
formData.append('files', file, file.webkitRelativePath || file.name);
});
fetch('/upload-folder', { method: 'POST', body: formData })
.then(r => r.json())
.then(console.log);
});
XMLHttpRequest 上传并监控进度
如果你需要上传进度条(尤其是大文件夹场景),XMLHttpRequest 是唯一选择,因为 fetch 目前不支持上传进度事件。
注意细节:
- 必须显式设置
xhr.upload.onprogress,而不是xhr.onprogress -
FormData.append()的第三个参数(文件名)同样生效,和fetch行为一致 - 不要调用
xhr.setRequestHeader('Content-Type', ...)——交给浏览器自动设为multipart/form-data; boundary=...,否则会破坏二进制边界 - 服务端接收逻辑必须兼容同名字段(
files)传入多个文件,不能只取第一个
错误典型表现:400 Bad Request 或服务端只收到一个文件,往往是因为手动设置了 Content-Type 或没正确遍历 FileList。
没有真正的“同步上传文件夹”这回事
所谓“同步”,指表单 submit 刷新页面。但 HTML 表单规范根本不定义目录上传语义,webkitdirectory 是 JS 层面的扩展,与表单提交解耦。试图用 <form enctype="multipart/form-data"></form> 包裹 input[webkitdirectory],只会上传选中的顶层目录对象(实际为空或报错),子文件完全不可见。
容易被忽略的硬限制:
- Firefox 完全不支持
webkitdirectory,也没等效标准属性(directory提案已被废弃) - 移动端 Safari 和 Android Chrome 均不支持该属性,文件夹上传基本是桌面端专属功能
- 用户授权的是“访问该目录下所有文件”,不是“递归扫描子目录”——如果子目录里有符号链接或权限受限文件,它们不会出现在
FileList中



















