You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取当前目录的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 13:15:03