Start · Sprachen · JavaScript · Referenz · FileSystemHandle

FileSystemHandle

Schnittstelle

Basis-Interface der File System API. Es steht für einen Datei- oder Verzeichniseintrag und stellt <code>kind</code>, <code>name</code> und den Vergleich mit <code>isSameEntry()</code> bereit.

seit JavaScript Baseline 2023 (OPFS über navigator.storage.getDire Kategorie: webapi

Signatur

interface FileSystemHandle

Beschreibung

FileSystemHandle ist die gemeinsame Basis von FileSystemFileHandle (Dateien) und FileSystemDirectoryHandle (Verzeichnisse). Man erzeugt es nie direkt mit new, sondern bekommt es von einer anderen Stelle: von window.showOpenFilePicker(), showSaveFilePicker() oder showDirectoryPicker(), von navigator.storage.getDirectory() (Origin Private File System, kurz OPFS), beim Durchlaufen eines Verzeichnis-Handles oder bei Drag & Drop über DataTransferItem.getAsFileSystemHandle().

Das Interface stellt Folgendes bereit:

  • kind (nur lesbar): "file" oder "directory". Damit unterscheidet man die Art des Eintrags, zum Beispiel beim Durchlaufen eines Verzeichnisses.
  • name (nur lesbar): der Name des Eintrags ohne Pfad.
  • isSameEntry(other): prüft, ob zwei Handles auf denselben Eintrag zeigen. Gibt ein Promise<boolean> zurück.
  • queryPermission(descriptor) / requestPermission(descriptor) (experimentell, Chromium): fragen die Lese- oder Schreibberechtigung ab bzw. fordern sie an.
  • remove(options) (nicht standardisiert, Chromium): löscht den Eintrag selbst.

Handles sind serialisierbar. Man kann sie also in IndexedDB speichern oder per postMessage() an Worker schicken. So findet eine Web-App eine zuletzt geöffnete Datei auch nach einem Neuladen der Seite wieder. Die Berechtigung wird dabei aber nicht dauerhaft mitgespeichert. Sie muss später meist neu bestätigt werden.

Parameter

Name Typ Default Beschreibung
$other Pflicht FileSystemHandle Parameter von isSameEntry(other): das Handle, mit dem verglichen wird.
$descriptor { mode?: 'read' | 'readwrite' } { mode: 'read' } Parameter von queryPermission() und requestPermission(). mode legt fest, ob nur Lese- oder auch Schreibrechte geprüft bzw. angefordert werden.
$options { recursive?: boolean } { recursive: false } Parameter von remove(options) (nicht standardisiert). Mit recursive: true lassen sich auch Verzeichnisse löschen, die nicht leer sind.

Rückgabewert

Typ
FileSystemHandle
Beschreibung
Wird nicht direkt erzeugt. Man erhält eine Instanz der Unterklasse FileSystemFileHandle oder FileSystemDirectoryHandle. isSameEntry() gibt Promise<boolean> zurück, queryPermission() und requestPermission() geben Promise<'granted' | 'denied' | 'prompt'> zurück, remove() gibt Promise<void> zurück.

Beispiele

Handle per Datei-Dialog holen und kind/name auswerten (Chromium)

// Muss durch eine Nutzeraktion ausgelöst werden, z. B. einen Klick
document.querySelector('#open').addEventListener('click', async () => {
  try {
    const [handle] = await window.showOpenFilePicker({
      types: [{ description: 'Textdateien', accept: { 'text/plain': ['.txt'] } }]
    });
    console.log(handle.kind, handle.name);
    if (handle.kind === 'file') {
      const file = await handle.getFile();
      console.log(`${file.size} Bytes`);
    }
  } catch (err) {
    if (err.name !== 'AbortError') throw err; // Nutzer hat abgebrochen
  }
});
file notizen.txt 1234 Bytes

Origin Private File System: Einträge auflisten und isSameEntry()

const root = await navigator.storage.getDirectory();
const a = await root.getFileHandle('daten.json', { create: true });
await root.getDirectoryHandle('cache', { create: true });

// Verzeichnis durchlaufen – jeder Wert ist ein FileSystemHandle
for await (const handle of root.values()) {
  console.log(`${handle.kind === 'directory' ? '📁' : '📄'} ${handle.name}`);
}

// Zeigen zwei Handles auf denselben Eintrag?
const b = await root.getFileHandle('daten.json');
console.log(await a.isSameEntry(b));
console.log(a === b);
📄 daten.json 📁 cache true false

Handle in IndexedDB speichern und Berechtigung erneut anfordern

const openDB = () => new Promise((resolve, reject) => {
  const req = indexedDB.open('handles', 1);
  req.onupgradeneeded = () => req.result.createObjectStore('store');
  req.onsuccess = () => resolve(req.result);
  req.onerror = () => reject(req.error);
});

const idb = (mode, fn) => openDB().then(db => new Promise((resolve, reject) => {
  const req = fn(db.transaction('store', mode).objectStore('store'));
  req.onsuccess = () => resolve(req.result);
  req.onerror = () => reject(req.error);
}));

export const saveHandle = handle => idb('readwrite', s => s.put(handle, 'lastFile'));

export const restoreHandle = async () => {
  const handle = await idb('readonly', s => s.get('lastFile'));
  if (!handle) return null;
  const opts = { mode: 'readwrite' };
  if ((await handle.queryPermission(opts)) === 'granted') return handle;
  // requestPermission braucht eine Nutzeraktion (Klick)
  return (await handle.requestPermission(opts)) === 'granted' ? handle : null;
};