如何获取当前目录的directoryHandle用于showSaveDirectoryPicker的startIn参数
如何获取目标目录的FileSystemDirectoryHandle用于showSaveDirectoryPicker的startIn参数
核心限制先说明
- 原生
<input type="file" webkitdirectory>是早期非标准实现,选择目录后只能获取到目录下的File对象列表,无法直接输出对应的FileSystemDirectoryHandle实例,和新版File System Access API没有做能力打通。 - 浏览器出于安全规则限制,不允许网页在无用户主动交互授权的情况下,直接获取本地文件系统任意目录的handle,包括你提到的「当前HTML文件所在的运行目录」,哪怕是本地file://协议打开的页面也没有例外。
可行实现方案
方案一:替换上传侧的目录选择逻辑(推荐)
直接用File System Access API的showDirectoryPicker()替代input[webkitdirectory]做上传场景的目录选择,一次授权后即可缓存handle复用在下载场景:
// 全局缓存目录handle,可持久化存储到IndexedDB实现跨会话复用 let cachedDirHandle = null; // 上传场景的目录选择逻辑,替代原input[webkitdirectory] async function selectUploadDir() { // 要求用户主动触发交互(比如点击按钮)才能调用 cachedDirHandle = await window.showDirectoryPicker({ mode: 'read' // 只读权限满足上传需求 }); // 遍历目录下文件的逻辑和原input效果完全一致 const fileList = []; async function traverseDir(handle, path = '') { for await (const entry of handle.values()) { if (entry.kind === 'file') { const file = await entry.getFile(); file.webkitRelativePath = `${path}${file.name}`; fileList.push(file); } else if (entry.kind === 'directory') { await traverseDir(entry, `${path}${entry.name}/`); } } } await traverseDir(cachedDirHandle); // 后续拿到fileList做上传逻辑即可 } // 下载场景调用保存目录选择器,直接用缓存的handle指定默认打开位置 async function selectSaveDir() { const saveDirHandle = await window.showSaveDirectoryPicker({ startIn: cachedDirHandle // 直接打开上次用户选的目录 }); // 后续写入文件逻辑 }
该方案的额外优势是可以将cachedDirHandle通过FileSystemHandle.requestPersistentPermission()申请持久化权限后存入IndexedDB,就算用户刷新页面也不用再次选择目录。
方案二:兼容原有input[webkitdirectory]逻辑
如果不想修改原有上传侧的代码,可在用户第一次通过input选择目录后,引导用户通过showDirectoryPicker()手动选择一次同一目录,缓存handle后后续下载场景即可复用,仅需要用户多操作一次,后续无额外成本。
内容的提问来源于stack exchange,提问作者David DiLaura
相关产品推荐
相关产品推荐

