Start · Sprachen · JavaScript · Referenz · FileSystemFileHandle

FileSystemFileHandle

Schnittstelle

Repräsentiert einen Verweis auf eine Datei im Dateisystem, über den sich ihr Inhalt als <code>File</code> lesen und per Stream oder synchronem Zugriff schreiben lässt.

seit JavaScript Chromium 86+ (Picker/Schreiben), OPFS: Baseline 20 Kategorie: webapi

Signatur

interface FileSystemFileHandle extends FileSystemHandle

Beschreibung

FileSystemFileHandle ist Teil der File System API und steht für eine einzelne Datei. Ein Handle ist nicht die Datei selbst, sondern ein Verweis darauf. Er erbt von FileSystemHandle die Eigenschaften kind (immer "file") und name sowie die Methoden isSameEntry(), queryPermission() und requestPermission().

Einen Handle bekommt man auf mehreren Wegen:

  • über window.showOpenFilePicker() bzw. window.showSaveFilePicker() (File System Access API, nur Chromium),
  • über FileSystemDirectoryHandle.getFileHandle(), etwa im Origin Private File System (OPFS) über navigator.storage.getDirectory(),
  • über Drag & Drop mit DataTransferItem.getAsFileSystemHandle().

Die wichtigsten Methoden:

  • getFile(): gibt ein Promise<File> mit einer Momentaufnahme des Inhalts zurück.
  • createWritable(options): gibt ein Promise<FileSystemWritableFileStream> zum Schreiben zurück. Die Änderungen landen erst bei close() in der Datei.
  • createSyncAccessHandle(options): gibt ein Promise<FileSystemSyncAccessHandle> für sehr schnelle, synchrone Lese- und Schreibzugriffe zurück. Das geht nur im OPFS und nur in Dedicated Workers.

Typische Einsatzfälle sind Editoren im Browser, die eine lokale Datei öffnen und wieder speichern („Speichern“ statt „Herunterladen“), sowie leistungsstarke Speicherung im OPFS, etwa für SQLite-WASM oder Offline-Caches.

Parameter

Name Typ Default Beschreibung
$options.keepExistingData boolean false Option für createWritable(). Bei true wird der bisherige Inhalt in die temporäre Datei kopiert, sodass man anhängen oder punktuell überschreiben kann. Bei false beginnt man mit einer leeren Datei.
$options.mode "exclusive" | "siloed" | "read-only" | "readwrite" | "readwrite-unsafe" "siloed" (createWritable) bzw. "readwrite" (createSyncAccessHandle) Sperrmodus, bislang nur in Chromium (ab 121) unterstützt. Für createWritable() sind "exclusive" und "siloed" erlaubt, für createSyncAccessHandle() die Werte "readwrite", "read-only" und "readwrite-unsafe".

Rückgabewert

Typ
FileSystemFileHandle
Beschreibung
Ein Handle-Objekt. Man erzeugt es nicht per Konstruktor, sondern erhält es von Pickern, von getFileHandle() oder über Drag & Drop. Seine Methoden liefern Promise<File>, Promise<FileSystemWritableFileStream> bzw. Promise<FileSystemSyncAccessHandle>.

Beispiele

Lokale Textdatei öffnen und lesen (File System Access API)

// Muss durch eine Nutzeraktion ausgelöst werden, z. B. einen Klick
const openButton = document.querySelector('#open');

openButton.addEventListener('click', async () => {
  try {
    const [fileHandle] = await window.showOpenFilePicker({
      types: [{ description: 'Textdateien', accept: { 'text/plain': ['.txt', '.md'] } }],
    });
    console.log(fileHandle.kind, fileHandle.name);

    const file = await fileHandle.getFile();
    const text = await file.text();
    console.log(`${file.size} Bytes gelesen`);
    document.querySelector('#editor').value = text;
  } catch (err) {
    if (err.name !== 'AbortError') console.error(err);
  }
});
file notizen.txt 1234 Bytes gelesen

Änderungen zurück in dieselbe Datei speichern

const saveFile = async (fileHandle, contents) => {
  // Berechtigung prüfen und bei Bedarf anfordern
  const opts = { mode: 'readwrite' };
  if ((await fileHandle.queryPermission(opts)) !== 'granted' &&
      (await fileHandle.requestPermission(opts)) !== 'granted') {
    throw new Error('Keine Schreibberechtigung');
  }

  const writable = await fileHandle.createWritable();
  await writable.write(contents);
  await writable.close(); // erst jetzt wird die Datei tatsächlich ersetzt
  console.log(`Gespeichert: ${fileHandle.name}`);
};

// Aufruf, z. B. nach showSaveFilePicker():
// const handle = await window.showSaveFilePicker({ suggestedName: 'export.json' });
// await saveFile(handle, JSON.stringify({ ok: true }, null, 2));
Gespeichert: export.json

Origin Private File System: Datei anlegen, anhängen, lesen

// Läuft in allen modernen Browsern, ohne Picker und ohne Berechtigungsdialog
const root = await navigator.storage.getDirectory();
const logHandle = await root.getFileHandle('app.log', { create: true });

const writable = await logHandle.createWritable({ keepExistingData: true });
const { size } = await logHandle.getFile();
await writable.seek(size); // ans Dateiende springen
await writable.write(`${new Date().toISOString()} App gestartet\n`);
await writable.close();

const log = await (await logHandle.getFile()).text();
console.log(log.trim().split('\n').at(-1));
2024-05-01T10:00:00.000Z App gestartet

Synchroner Zugriff im Dedicated Worker

// worker.js
self.onmessage = async ({ data }) => {
  const root = await navigator.storage.getDirectory();
  const handle = await root.getFileHandle('daten.bin', { create: true });
  const access = await handle.createSyncAccessHandle();

  const bytes = new TextEncoder().encode(data);
  access.truncate(0);
  access.write(bytes, { at: 0 });
  access.flush();

  const buffer = new Uint8Array(access.getSize());
  access.read(buffer, { at: 0 });
  access.close(); // Sperre wieder freigeben

  self.postMessage(new TextDecoder().decode(buffer));
};
(Nachricht an den Hauptthread mit dem geschriebenen Text)