webkitdirectory 必须与 type="file" 共用才生效,是 WebKit/Blink 私有布尔属性;单独使用、type 非 file、file:// 协议下均无效;正确写法为 ;仅 Chrome/Edge/Safari 16.4+ 支持,Firefox 不支持且无降级方案;选中后返回扁平化 FileList,依赖 file.webkitRelativePath 重建目录结构;不递归子目录,需 showDirectoryPicker() 或 ZIP 方案实现真正递归。

webkitdirectory 必须和 type="file" 一起用,否则不生效
单独写 webkitdirectory 属性,比如 ,浏览器会直接忽略——它不是独立控件,只是 的一个布尔开关。Chrome、Edge、Safari 16.4+ 只在同时看到 type="file" 和 webkitdirectory 时,才弹出「选择文件夹」对话框。
常见错误写法包括:
-
—— 属性不能带值,必须是纯布尔形式 -
—— type 不是 file,完全没反应 - 本地双击打开的
file://页面中使用 —— 大部分 Chromium 版本会静默禁用该功能
正确写法只有一行:。其中 directory 是历史兼容属性(已废弃但无害),multiple 在现代 Chrome 中实际被忽略,但加上更稳妥——某些旧版本若缺失,可能只返回空 FileList 或根本不出对话框。
Firefox 和 Safari 旧版根本不认 webkitdirectory
这个属性是 WebKit/Blink 私有实现,W3C 未标准化。Firefox 从早期就拒绝支持 webkitdirectory,也不提供等效替代;Safari 直到 16.4+ 才开始支持,且**必须同时声明 multiple**,否则行为异常(比如选中后 event.target.files.length === 0)。
真实项目中别指望“降级处理”:没有 polyfill,也没有 fallback API。如果业务要求覆盖 Firefox 用户,就得换方案,比如用 window.showDirectoryPicker()(需 HTTPS + 用户授权 + Chrome/Edge),或干脆放弃文件夹上传,改用 ZIP 手动压缩上传。
Electron 应用也常踩坑:默认 webPreferences 里禁用该能力,需显式开启 nodeIntegration 和 webviewTag(注意安全风险),否则即使代码写对也无效。
选中后拿到的是扁平化 FileList,不是目录树
用户点选一个文件夹(如 project/),event.target.files 返回的不是“一个 Directory 对象”,而是一堆 File 实例,每个都带 webkitRelativePath 字段,例如:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
files[0].webkitRelativePath // "src/index.js" files[1].webkitRelativePath // "public/logo.png" files[2].webkitRelativePath // "README.md"
关键点:
- 子目录本身不会出现在列表里(
project/assets/这个目录对象不会出现) - 所有路径都是相对于所选根目录的,不含盘符或绝对路径
-
file.name永远只是末级文件名(如"index.js"),不能用来还原结构 - 空子目录会被完全跳过,浏览器只递归收集文件,不保留目录节点
所以服务端重建目录,唯一可靠依据就是 file.webkitRelativePath。上传时必须用它作为 FormData.append() 的第三个参数:formData.append("file", file, file.webkitRelativePath),否则后端收到的只是裸文件名,无法还原层级。
不要试图用 webkitdirectory 递归读取多层子文件夹
这是最常被误解的一点:webkitdirectory 只展开所选文件夹的**直接子文件**,不进入任何子目录。选 foo/,得到 foo/a.txt、foo/b.jpg,但 foo/sub/c.log 不会出现——sub/ 这个目录对象压根不会被遍历,更不会生成对应 File。
想真正递归,必须切换技术栈:
- 用
showDirectoryPicker()+FileSystemDirectoryHandle手动遍历(仅 Chrome/Edge,需用户授权) - 前端打包成 ZIP 后上传,由后端解压(兼容性最好,但增加客户端 CPU 和内存压力)
- 分步上传:先选顶层目录,再让用户逐个点开子目录重新触发
webkitdirectory(体验差,极少采用)
别试 FileReader + webkitdirectory 组合——因为根本没有子目录的入口,连第一步都卡死。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










