HTML中如何用showDirectoryPicker选择文件夹

作者:袖梨 2026-06-07
showDirectoryPicker 是 Chromium 系统的原生 API,用于弹出文件夹选择对话框并返回 FileSystemDirectoryHandle 对象,但仅 Chrome 86+、Edge 91+、Opera 82+ 支持,Firefox/Safari 不支持,且须 HTTPS/localhost 安全上下文及用户手势触发。

showDirectoryPicker 是什么,能不能直接用

showDirectoryPicker 是浏览器原生提供的 API,用于弹出系统文件夹选择对话框,返回一个 FileSystemDirectoryHandle 对象。但它不是所有浏览器都支持——目前仅 Chromium 内核(Chrome 86+、Edge 91+、Opera 82+)支持,Firefox 和 Safari 完全不支持,且必须运行在安全上下文(https://localhost)中。

调用前必须由用户手势触发(比如点击按钮),不能在页面加载时自动执行,否则会抛出 DOMException: Permission denied

基础用法:一次选中整个文件夹

最简路径就是调用 showDirectoryPicker() 并 await 结果:

async function pickFolder() {  try {    const dirHandle = await window.showDirectoryPicker();    console.log('选中的文件夹名:', dirHandle.name);    return dirHandle;  } catch (err) {    console.error('用户取消或拒绝权限:', err.message);  }}

注意几点:

立即学习“前端免费学习笔记(深入)”;

  • showDirectoryPicker() 返回的是 handle,不是路径字符串,无法直接读取磁盘路径(出于安全限制)
  • 返回的 dirHandle 可以用来遍历子文件/子目录(通过 dirHandle.values()dirHandle.getEntries()
  • 首次调用会弹出权限请求,用户点“允许”后,该站点后续调用无需再次确认(除非用户手动清除权限)

常见报错和绕不过去的坑

实际写的时候容易遇到这些错误:

  • TypeError: showDirectoryPicker is not a function:当前浏览器不支持,需先检测 if ('showDirectoryPicker' in window)
  • DOMException: Permission denied:没在用户点击等手势回调里调用,比如放在 setTimeoutfetch.then 或页面初始化中
  • SecurityError: Permission denied:页面非 HTTPS(生产环境)或非 localhost(开发环境)
  • 选中文件夹后无法读取内容:未对每个 FileSystemHandle 显式调用 getFileHandle()getDirectoryHandle() 获取访问权,尤其嵌套层级深时容易漏掉

读取文件夹内文件的最小可行示例

拿到 dirHandle 后,要逐个处理条目,注意它返回的是异步迭代器:

async function listFiles(dirHandle) {  for await (const entry of dirHandle.values()) {    if (entry.kind === 'file') {      const file = await entry.getFile();      console.log('文件名:', file.name, '大小:', file.size);    } else if (entry.kind === 'directory') {      console.log('子目录:', entry.name);      // 递归进入子目录需重新调用 entry.getDirectoryHandle()      // 注意:这会再次触发权限请求(如果未提前授权)    }  }}

关键提醒:

  • for await...of 是必须的,普通 for...of 不行
  • 对子目录调用 entry.getDirectoryHandle() 时,若用户之前只授权了顶层目录,会再次弹窗请求权限
  • 没有“一次性获取所有文件路径”的方法,必须手动遍历 + 逐个 getFile()

真正难的不是调用 API,而是处理权限粒度、递归深度、大文件列表性能,以及降级方案(比如 fallback 到 <input type="file" webkitdirectory>,但那个只在 Chrome 有效且不返回 handle)。

相关文章

精彩推荐