文件系统访问 API:是否可以存储已保存或已加载文件的 fileHandle 以供以后使用?

Cha*_*son 6 javascript serialization indexeddb

在使用新的(ish)文件系统访问 API的应用程序上工作,我想保存最近加载的文件的文件句柄,以显示“最近的文件...”菜单选项并让用户加载这些文件之一而不打开系统文件选择窗口。

这篇文章有一段关于在IndexedDB中存储fileHandles,它提到从API返回的句柄是“可序列化的”,但它没有任何示例代码,JSON.stringify不会这样做。

文件句柄是可序列化的,这意味着您可以将文件句柄保存到 IndexedDB,或调用 postMessage() 在同一顶级源之间发送它们。

有没有办法序列化 JSON 以外的句柄?我认为 IndexedDB 可能会自动执行此操作,但这似乎也不起作用。

Sem*_*lon 8

当平台接口为 时[Serializable],意味着它具有关联的内部序列化和反序列化规则,执行 \xe2\x80\x9c 结构化克隆\xe2\x80\x9d 算法的 API 将使用这些规则来创建 \xe2\x80\x9ccopies\xe2\ x80\x9d 的 JS 值。如前所述,消息 API 使用结构化克隆。它\xe2\x80\x99s 也被History API 使用,所以至少在理论上你可以将FileHandle 对象与历史条目关联起来。

\n

在撰写本文时,在 Chromium 中,FileHandle对象在一般情况下使用时似乎可以成功序列化和反序列化history.state,例如跨重新加载和向后导航。奇怪的是,当返回到前向条目时,反序列化似乎可能会默默地失败:null当向前遍历到关联状态包括一个或多个 FileHandles 的条目时,popStateEvent.state 和 History.state 总是返回。这似乎是一个错误。

\n

历史条目是 \xe2\x80\x9csession\xe2\x80\x9d 存储 \xe2\x80\x9cshelf\xe2\x80\x9d 的一部分。这里的会话(大致)指的是\xe2\x80\x9c选项卡/窗口\xe2\x80\x9d的生命周期。有时这可能正是您想要的 FileHandle(例如,向后遍历时,重新打开在先前状态下打开的文件)。但是,它对跨多个会话保留的 \xe2\x80\x99d 生命周期存储没有帮助。据我所知,唯一可以序列化和反序列化 FileHandle 以进行原始级存储的 API 是 IndexedDB。

\n


Den*_*er9 5

这是一个最小的示例,它演示了如何FileSystemHandle在 IndexedDB 中存储和检索文件句柄(准确地说是 a)(为了简洁,代码使用idb-keyval库):

import { get, set } from 'https://unpkg.com/idb-keyval@5.0.2/dist/esm/index.js';

const pre = document.querySelector('pre');
const button = document.querySelector('button');

button.addEventListener('click', async () => {
  try {
    const fileHandleOrUndefined = await get('file');    
    if (fileHandleOrUndefined) {      
      pre.textContent =
          `Retrieved file handle "${fileHandleOrUndefined.name}" from IndexedDB.`;
      return;
    }
    // This always returns an array, but we just need the first entry.
    const [fileHandle] = await window.showOpenFilePicker();
    await set('file', fileHandle);    
    pre.textContent =
        `Stored file handle for "${fileHandle.name}" in IndexedDB.`;
  } catch (error) {
    alert(error.name, error.message);
  }
});
Run Code Online (Sandbox Code Playgroud)

我已经创建了一个演示,显示了上面的代码。

  • 很可能不是,因为它是根据本地存储建模的,本地存储会转换为字符串,这意味着它无法序列化文件句柄。 (3认同)