webkitdirectory 是目前唯一原生支持文件夹选择的 HTML5 属性,仅 Chrome、Edge 和新版 Safari 支持,需配合 multiple 使用,通过 File.webkitRelativePath 获取路径信息,并需前端逐个上传及后端协同确认整体成功。

HTML5 webkitdirectory 属性是唯一原生支持文件夹上传的机制
浏览器原生不支持直接上传整个文件夹,但 Chrome、Edge(基于 Chromium)和新版 Safari 支持 webkitdirectory 属性,它能让 <input type="file"> 触发系统级文件夹选择对话框,并递归列出所有子文件(含路径信息)。Firefox 不支持该属性,会退化为单文件选择;IE 完全不支持。
关键点在于:webkitdirectory 本身不上传,只提供文件列表;你仍需用 XMLHttpRequest 或 fetch 逐个或分片发送这些 File 对象。
- 必须显式添加
webkitdirectory和directory(W3C 标准草案属性,目前仅示意用途,实际生效靠前者) -
multiple属性必须同时存在,否则只返回根目录下的文件(不含子目录内文件) - 获取到的
event.target.files是扁平化的FileList,每个File的webkitRelativePath属性保存了其在原始文件夹中的相对路径,例如"project/src/index.js" - 不支持拖拽整个文件夹到页面(
drop事件中dataTransfer.items无法读取目录结构,Chrome 会过滤掉目录项)
监听“上传成功”不能只看 xhr.onload 或 fetch().then()
文件夹上传本质是多个文件的并发/串行请求,所谓“整体成功”,必须等所有子文件都返回有效响应且服务端确认合并完成(如生成 ZIP、写入数据库记录、触发回调钩子),前端才能算真正完成。
常见错误是:把某个单文件的 xhr.status === 200 当作整个文件夹上传成功——这完全不可靠,尤其当后端采用分片、异步处理或队列模式时。
立即学习“前端免费学习笔记(深入)”;
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 推荐方案:前端维护一个计数器 + 成功 ID 集合,每完成一个文件就
push其name或id,最后比对是否与原始FileList.length一致 - 更健壮的做法:后端提供一个
/upload/status?task_id=xxx接口,前端轮询直到返回{"status": "completed"},再触发最终的成功回调 - 避免用
Promise.all()包裹全部上传请求——某个失败会导致整个 Promise 拒绝,掩盖部分成功结果;改用Promise.allSettled()并检查每个结果的status字段
上传过程中必须保留 webkitRelativePath 并透传给后端
如果目标是还原文件夹结构(比如存到对象存储的 bucket/project/src/ 路径下),前端必须把每个 File 的 webkitRelativePath 作为元数据一并提交,否则后端无法知道该放在哪一级目录。
常见做法是在 FormData 中额外 append 一个字段:
const formData = new FormData();
formData.append('file', file);
formData.append('relative_path', file.webkitRelativePath); // 关键!
后端收到后,用这个值拼接存储路径,而不是简单按文件名去重或覆盖。
- 注意:
webkitRelativePath在 Firefox 中为"",需提前检测并降级处理(如提示“请使用 Chrome 或 Edge 浏览器上传文件夹”) - 某些旧版 Chrome(
- 不要尝试用
file.path—— 它在所有现代浏览器中都被禁用,返回undefined或空字符串,出于安全限制
真正落地时,webkitdirectory 只是起点,不是解决方案
企业级场景(比如汽车制造客户要集成进 OA 系统)几乎不会只依赖原生 webkitdirectory。它缺乏断点续传、大文件分片、MD5 校验、秒传、权限控制等关键能力。实际项目中,99% 的“文件夹上传”都是基于 WebUploader、Uppy 或自研 SDK 实现的,它们底层仍调用 webkitdirectory 获取文件列表,但封装了传输层逻辑。
如果你正卡在“怎么让上传完执行下一步”,最可能的问题不是监听没写对,而是后端没提供明确的完成信号。先确认后端接口文档里有没有 task_id、upload_id 这类标识,以及对应的查询接口——没有这个,前端所谓“成功”就是空中楼阁。


















