showDirectoryPicker 是 Chromium 系统的原生 API,用于弹出文件夹选择对话框并返回 FileSystemDirectoryHandle 对象,但仅 Chrome 86+、Edge 91+、Opera 82+ 支持,Firefox/Safari 不支持,且须 HTTPS/localhost 安全上下文及用户手势触发。
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:没在用户点击等手势回调里调用,比如放在 setTimeout、fetch.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)。