html无法直接读取文件夹内容,浏览器安全限制使默认不支持选文件夹;需用webkitdirectory(chrome/safari/edge)或directory(仅firefox)属性配合multiple,但仅返回顶层条目且不递归。

HTML 无法直接读取文件夹内容
浏览器出于安全限制,<input type="file"> 默认不支持选取整个文件夹并列出其所有文件名。所谓“选择文件夹”,实际是启用 webkitdirectory(非标准但广泛支持)或 directory(新标准,支持有限)属性,让用户选中一个目录,再由 JS 逐个读取其中的 File 对象——但注意:这仍只返回该目录**顶层**的文件和子目录条目,不递归。
input[type="file"] 启用目录选择的写法差异
两种主流方式,行为和兼容性不同:
-
<input type="file" webkitdirectory="webkitdirectory" directory="directory" multiple>:最常用,Chrome/Edge/Safari 支持良好;Firefox 仅支持directory(需显式设为directory=""),且要求 HTTPS 或 localhost -
<input type="file" directory="">:W3C 标准属性,但目前仅 Firefox 原生支持;Chrome 等忽略它,退而使用webkitdirectory - 必须带
multiple,否则即使选中目录,也只返回第一个条目 - 用户点击后看到的是“选择文件夹”对话框,不是“选择多个文件”——这是关键体验区别
获取选中文件夹内所有文件名(含子目录)要自己递归
浏览器只提供目录下的一级 File 或 FileSystemHandle(后者需 showDirectoryPicker() API),没有现成的 readdir。想拿到所有文件名(尤其含嵌套路径),得手动遍历:
- 用
webkitdirectory方式时,event.target.files是FileList,每个File的webkitRelativePath字段包含相对于所选文件夹的路径(如"docs/report.pdf"),可直接提取文件名 - 用
showDirectoryPicker()(推荐但兼容性差):返回FileSystemDirectoryHandle,调用handle.values()+ 递归isFile()/isDirectory()判断,再用getFile()读取元数据 - 注意:
webkitRelativePath在 Firefox 中为空,所以不能只依赖它;showDirectoryPicker()需要https://或localhost,HTTP 页面直接报错SecurityError - 简单示例(仅处理一级):
input.addEventListener('change', e => { Array.from(e.target.files).forEach(file => { console.log(file.name); // 仅文件名 console.log(file.webkitRelativePath); // 完整相对路径(Chrome/Safari) }); });
常见错误现象与绕不过的限制
很多开发者卡在以下几点:
立即学习“前端免费学习笔记(深入)”;
- 用了
directory却没加multiple→ 控制台无报错,但files.length === 0或只返回一个空File - 在 HTTP 页面调用
showDirectoryPicker()→ 控制台明确报错Uncaught TypeError: showDirectoryPicker is not a function或SecurityError - 期望一次性拿到绝对路径(如
C:\xxx)→ 浏览器禁止暴露真实路径,webkitRelativePath是唯一可用的路径信息,且仅限同源 - 想用 Node.js 的
fs.readdirSync→ HTML 运行在浏览器环境,无权访问本地文件系统,此路不通 - 递归遍历时未处理 Promise 链或异步循环 → 导致只打印出部分文件名,或顺序混乱
真正能稳定跨浏览器拿到“所有文件名”的方案,目前只有 webkitdirectory + webkitRelativePath,但得接受它不支持 Firefox。如果必须全兼容,只能引导用户手动多选文件,或改用桌面端方案(如 Electron)。










