文件系统访问(File System Access) API

2024/09/05

File API 文件 API

对于传统的File API 当需要用户提供文件时,Web 应用程序可以使用文件 <input> 元素打开文件选择对话框来访问文件或者文件夹

fileInput.addEventListener('change', async () => {
  const [file] = fileInput.files;
});

File System Access API

借助 File System Access API,开发者可以构建功能强大的 Web 应用, 用户本地设备上的文件,例如 IDE、照片和视频编辑器、文本编辑器等。更新后 当用户向 Web 应用授予访问权限时,此 API 可让用户直接读取或保存对文件的更改,以及 文件夹。除了读取和写入文件以外,File System Access API 还提供了 能够打开目录并枚举其内容。

File System Access API 的主要特性

请求文件权限

async function openFile() {
  const [fileHandle] = await window.showOpenFilePicker();
  // 对文件进行处理
}

async function openFolder() {
  const folderHandle = await window.showDirectoryPicker();
  // 对文件夹进行处理
}

持久化访问权限

用户可以授予 Web 应用程序对特定文件或文件夹的。 一旦获得权限,应用程序可以在后续的访问中无需再次请求用户授权,直接访问这些文件或文件夹。

let DB;

// 文件句柄和目录句柄是可序列化的,这意味着您可以保存文件或 将目录句柄添加到 IndexedDB,或调用 postMessage() 在同一顶级数据库之间发送这些路径和 来源。
async function getDB(DB_NAME, STORE_NAME) {
  const dbPromise = await openDB(DB_NAME, 1, {
    upgrade(db) {
      db.createObjectStore(STORE_NAME);
    },
  });

  async function get(key) {
    return dbPromise.get(STORE_NAME, key);
  }
  async function set(key, val) {
    return dbPromise.put(STORE_NAME, val, key);
  }
  async function del(key) {
    return dbPromise.delete(STORE_NAME, key);
  }

  return {
    get,
    set,
    del,
  };
}

export async function getDirHandler(DB_DIR_KEY = 'dir_handler') {
  if (!DB) {
    DB = await getDB(DB_NAME, STORE_NAME);
  }
  /** @type { FileSystemDirectoryHandle } */
  let dirHandler = await DB.get(DB_DIR_KEY);
  if (!dirHandler) {
    try {
      dirHandler = await window.showDirectoryPicker({
        mode: 'readwrite',
        startIn: 'documents',
      });
    } catch (error) {
      console.log(error);
    }

    await DB.set(DB_DIR_KEY, dirHandler);
  }

  // 由于权限并非总是在会话之间持久保留,因此您应验证用户是否 已使用 queryPermission() 授予对文件或目录的权限。否则,请调用 requestPermission() 来(重新)请求该请求。这对文件和目录句柄是相同的。您 需要运行 fileOrDirectoryHandle.requestPermission(descriptor) 或 fileOrDirectoryHandle.queryPermission(descriptor)
  await verifyPermission(dirHandler);
  return dirHandler;
}

直接文件访问

可以通过编程方式直接打开、读取、写入和保存文件,无需依赖传统的文件选择对话框。 例如,可以使用 JavaScript 代码直接访问用户指定的文件,并对其内容进行处理

async function readFileContent(fileHandle, type) {
  const file = await fileHandle.getFile();
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onerror = reject;
    reader.onload = () => resolve(reader.result);
    reader.readAsText(file);
  });
}

使用限制