Search code examples
javascriptserializationindexeddb

File System Access API: is it possible to store the fileHandle of a saved or loaded file for later use?


Working on an app that uses the new(ish) File System Access API, and I wanted to save the fileHandles of recently loaded files, to display a "Recent Files..." menu option and let a user load one of these files without opening the system file selection window.

This article has a paragraph about storing fileHandles in IndexedDB and it mentions that the handles returned from the API are "serializable," but it doesn't have any example code, and JSON.stringify won't do it.

File handles are serializable, which means that you can save a file handle to IndexedDB, or call postMessage() to send them between the same top-level origin.

Is there a way to serialize the handle other than JSON? I thought maybe IndexedDB would do it automatically but that doesn't seem to work, either.


Solution

  • Here is a minimal example that demonstrates how to store and retrieve a file handle (a FileSystemHandle to be precise) in IndexedDB (the code uses the idb-keyval library for brevity):

    import { get, set } from 'https://unpkg.com/[email protected]/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);
      }
    });
    

    I have created a demo that shows the above code in action.