Start · Sprachen · JavaScript · Referenz · FileSystemDirectoryHandle

FileSystemDirectoryHandle

Schnittstelle

Ein <code>FileSystemDirectoryHandle</code> steht für ein Verzeichnis im Dateisystem. Damit legt man Dateien und Unterordner an, liest sie aus und löscht sie.

seit JavaScript Baseline 2023 (OPFS in allen modernen Browsern); s Kategorie: webapi

Signatur

interface FileSystemDirectoryHandle extends FileSystemHandle

Beschreibung

FileSystemDirectoryHandle gehört zur File System API und erbt von FileSystemHandle. Über ein solches Handle greift man auf ein Verzeichnis zu. Das kann ein Ordner sein, den der Nutzer über window.showDirectoryPicker() ausgewählt hat. Es kann aber auch das Wurzelverzeichnis des Origin Private File System (OPFS) sein, das man über navigator.storage.getDirectory() erhält.

Die wichtigsten Methoden:

  • getFileHandle(name, { create }) gibt ein FileSystemFileHandle für eine Datei im Verzeichnis zurück und legt die Datei bei Bedarf an.
  • getDirectoryHandle(name, { create }) gibt ein Handle für einen Unterordner zurück und legt ihn bei Bedarf an.
  • removeEntry(name, { recursive }) löscht eine Datei oder einen Ordner.
  • resolve(possibleDescendant) liefert den relativen Pfad zu einem untergeordneten Handle als Array von Namen. Ist das Handle kein Nachfahre, ist das Ergebnis null.
  • entries(), keys(), values() und [Symbol.asyncIterator] sind asynchrone Iteratoren über den Inhalt des Verzeichnisses. Man nutzt sie mit for await…of.

Die Schnittstelle eignet sich für Editoren, Foto- oder Projektverwaltungen, die mit lokalen Ordnern arbeiten. Im OPFS dient sie als schneller, privater Speicher, zum Beispiel für SQLite-Datenbanken in WebAssembly. Alle Methoden arbeiten asynchron und geben Promises zurück. Die geerbten Eigenschaften kind (hier immer "directory") und name beschreiben das Handle.

Parameter

Name Typ Default Beschreibung
$name Pflicht string Name des Eintrags im Verzeichnis. Wird von getFileHandle(), getDirectoryHandle() und removeEntry() verwendet. Pfade mit / sind nicht erlaubt.
$options.create boolean false Bei getFileHandle()/getDirectoryHandle(): legt den Eintrag an, falls er noch nicht existiert.
$options.recursive boolean false Bei removeEntry(): löscht auch Ordner, die nicht leer sind, samt Inhalt.
$possibleDescendant FileSystemHandle Bei resolve(): das Handle, dessen relativer Pfad bestimmt werden soll.

Rückgabewert

Typ
FileSystemDirectoryHandle
Beschreibung
Ein Handle-Objekt. Man erhält es von showDirectoryPicker(), navigator.storage.getDirectory(), getDirectoryHandle() oder DataTransferItem.getAsFileSystemHandle(). Einen öffentlichen Konstruktor gibt es nicht.

Beispiele

Datei im Origin Private File System anlegen und lesen

const root = await navigator.storage.getDirectory();

// Unterordner und Datei anlegen (create: true)
const notesDir = await root.getDirectoryHandle('notizen', { create: true });
const fileHandle = await notesDir.getFileHandle('todo.txt', { create: true });

// Schreiben
const writable = await fileHandle.createWritable();
await writable.write('Milch kaufen\nCode reviewen');
await writable.close();

// Lesen
const file = await fileHandle.getFile();
console.log(notesDir.kind, notesDir.name);
console.log(await file.text());
directory notizen Milch kaufen Code reviewen

Vom Nutzer gewählten Ordner auflisten

document.querySelector('#open').addEventListener('click', async () => {
  try {
    const dirHandle = await window.showDirectoryPicker({ mode: 'read' });
    for await (const [name, handle] of dirHandle.entries()) {
      console.log(handle.kind === 'directory' ? `📁 ${name}` : `📄 ${name}`);
    }
  } catch (err) {
    if (err.name === 'AbortError') console.log('Auswahl abgebrochen');
    else throw err;
  }
});
📁 src 📄 package.json 📄 README.md

Rekursiv alle Dateien sammeln und relativen Pfad ermitteln

const walk = async function* (dir) {
  for await (const handle of dir.values()) {
    if (handle.kind === 'file') yield handle;
    else yield* walk(handle);
  }
};

const root = await navigator.storage.getDirectory();
const sub = await root.getDirectoryHandle('a', { create: true });
await sub.getFileHandle('b.txt', { create: true });

for await (const file of walk(root)) {
  const path = await root.resolve(file);
  console.log(path.join('/'));
}
a/b.txt notizen/todo.txt

Einträge löschen

const root = await navigator.storage.getDirectory();

// Einzelne Datei löschen
await root.getDirectoryHandle('a').then((d) => d.removeEntry('b.txt'));

// Ordner inklusive Inhalt löschen
await root.removeEntry('notizen', { recursive: true });

const names = [];
for await (const name of root.keys()) names.push(name);
console.log(names);
["a"]

// Wichtig · Fallstricke

  • Browser-Unterstützung: Das OPFS über navigator.storage.getDirectory() funktioniert in Chrome, Edge, Firefox und Safari. showDirectoryPicker() für echte Ordner des Nutzers gibt es nur in Chromium-Browsern. Vor der Nutzung sollte man prüfen, ob die Funktion vorhanden ist ('showDirectoryPicker' in window).
  • Die API ist nur in einem sicheren Kontext (HTTPS) verfügbar. showDirectoryPicker() braucht außerdem eine Nutzeraktion, etwa einen Klick. Bricht der Nutzer die Auswahl ab, wird ein AbortError ausgelöst.
  • Die Berechtigungen können wegfallen. Handles lassen sich zwar in IndexedDB speichern. Nach einem Neuladen der Seite muss man die Berechtigung aber mit queryPermission() prüfen und bei Bedarf mit requestPermission({ mode: 'readwrite' }) neu anfordern (nur Chromium).
  • Häufige Fehler: getFileHandle() ohne create: true löst bei einem fehlenden Eintrag einen NotFoundError aus. Existiert unter dem Namen der falsche Typ (Datei statt Ordner), gibt es einen TypeMismatchError. removeEntry() auf einem nicht leeren Ordner ohne recursive: true löst einen InvalidModificationError aus.
  • Die Reihenfolge beim Durchlaufen mit entries() ist nicht festgelegt. Wer sortierte Ausgaben braucht, sortiert selbst.
  • Das OPFS ist für den Nutzer nicht sichtbar. Der Browser kann es löschen, wenn der Speicher knapp wird. Mit navigator.storage.persist() lässt sich dauerhafte Speicherung anfordern.