Start · Sprachen · JavaScript · Referenz · StorageAccessHandle.getDirectory()

StorageAccessHandle.getDirectory()

Methode

Gibt ein Promise zurück, das mit einem nicht partitionierten <code>FileSystemDirectoryHandle</code> auf das Stammverzeichnis des Origin Private File System (OPFS) erfüllt wird.

seit JavaScript Chromium 125+ (Chrome, Edge); nicht in Firefox und Kategorie: webapi

Signatur

StorageAccessHandle.prototype.getDirectory()

Beschreibung

getDirectory() ist eine Methode des StorageAccessHandle. Dieses Objekt erhalten eingebettete Drittanbieter-Inhalte, meist in einem <iframe>, über document.requestStorageAccess(types). Die Methode funktioniert wie navigator.storage.getDirectory(), mit einem wichtigen Unterschied: Sie liefert das Stammverzeichnis des nicht partitionierten Origin Private File System (OPFS). Das ist dasselbe Dateisystem, das der Origin sieht, wenn er als Hauptseite (First Party) geöffnet ist.

Normalerweise trennen Browser den Speicher eingebetteter Inhalte nach der obersten Website. Ein Widget von widget.example auf shop.example sieht also ein anderes OPFS als dasselbe Widget auf blog.example. Mit getDirectory() kann ein eingebettetes Widget nach der Zustimmung der Person auf seine eigenen Daten aus dem First-Party-Kontext zugreifen, zum Beispiel auf zwischengespeicherte Dokumente, Einstellungen oder eine SQLite-Datenbank im OPFS.

Die Methode funktioniert nur, wenn beim Aufruf von requestStorageAccess() ausdrücklich { getDirectory: true } oder { all: true } angefordert wurde. Das zurückgegebene FileSystemDirectoryHandle wird wie gewohnt genutzt: getFileHandle(), getDirectoryHandle(), createWritable(), removeEntry() und so weiter.

Rückgabewert

Typ
Promise<FileSystemDirectoryHandle>
Beschreibung
Ein Promise, das mit dem FileSystemDirectoryHandle des Stammverzeichnisses des nicht partitionierten OPFS erfüllt wird. Es wird mit einer DOMException abgelehnt (meist SecurityError), wenn getDirectory beim Anfordern des Zugriffs nicht verlangt wurde oder der Zugriff auf den Speicher nicht erlaubt ist.

Beispiele

Speicherzugriff anfordern und das Stammverzeichnis öffnen

// Läuft in einem eingebetteten iframe eines Drittanbieters
const button = document.querySelector('#zugriff-erlauben');

button.addEventListener('click', async () => {
  try {
    // Muss durch eine Nutzeraktion ausgelöst werden
    const handle = await document.requestStorageAccess({ getDirectory: true });
    const root = await handle.getDirectory();
    console.log('Nicht partitioniertes OPFS:', root.kind, root.name);
  } catch (err) {
    console.error('Kein Zugriff:', err.name, err.message);
  }
});
Nicht partitioniertes OPFS: directory

Einstellungen aus dem First-Party-OPFS lesen und schreiben

const ladeEinstellungen = async (root) => {
  try {
    const fileHandle = await root.getFileHandle('einstellungen.json');
    const file = await fileHandle.getFile();
    return JSON.parse(await file.text());
  } catch (err) {
    if (err.name === 'NotFoundError') return { theme: 'hell' };
    throw err;
  }
};

const speichereEinstellungen = async (root, daten) => {
  const fileHandle = await root.getFileHandle('einstellungen.json', { create: true });
  const writable = await fileHandle.createWritable();
  await writable.write(JSON.stringify(daten));
  await writable.close();
};

document.querySelector('#laden').addEventListener('click', async () => {
  const sah = await document.requestStorageAccess({ getDirectory: true });
  const root = await sah.getDirectory();
  const settings = await ladeEinstellungen(root);
  console.log('Geladen:', settings);
  await speichereEinstellungen(root, { ...settings, zuletztGeoeffnet: Date.now() });
});
Geladen: { theme: 'hell' }

Feature-Erkennung mit Rückfall auf das partitionierte OPFS

const holeOpfsRoot = async () => {
  const unterstuetzt =
    typeof document.requestStorageAccess === 'function' &&
    typeof StorageAccessHandle !== 'undefined' &&
    'getDirectory' in StorageAccessHandle.prototype;

  if (unterstuetzt) {
    try {
      const sah = await document.requestStorageAccess({ getDirectory: true });
      return { root: await sah.getDirectory(), partitioniert: false };
    } catch {
      // Zugriff verweigert, weiter mit dem Rückfall
    }
  }
  // Rückfall: partitioniertes OPFS des aktuellen Kontexts
  return { root: await navigator.storage.getDirectory(), partitioniert: true };
};

document.querySelector('#start').addEventListener('click', async () => {
  const { root, partitioniert } = await holeOpfsRoot();
  const eintraege = [];
  for await (const name of root.keys()) eintraege.push(name);
  console.log({ partitioniert, eintraege });
});
{ partitioniert: false, eintraege: ['einstellungen.json'] }

// Wichtig · Fallstricke

  • Nur mit ausdrücklicher Anforderung: Wurde requestStorageAccess() ohne getDirectory: true (oder all: true) aufgerufen, wird das Promise mit einer DOMException abgelehnt. Wer ohne Argument aufruft, bekommt nur Zugriff auf Cookies und keinen StorageAccessHandle.
  • Nutzeraktion nötig: requestStorageAccess() braucht in der Regel eine vorübergehende Nutzeraktion, zum Beispiel einen Klick. Außerdem muss das iframe die Erlaubnis storage-access haben, bei Sandbox-iframes über allow-storage-access-by-user-activation.
  • Sicherer Kontext: Die API steht nur über HTTPS zur Verfügung.
  • Partitioniert und nicht partitioniert nicht verwechseln: navigator.storage.getDirectory() im iframe liefert weiterhin das partitionierte OPFS. Nur das Handle aus getDirectory() zeigt auf die First-Party-Daten.
  • Browser-Unterstützung: Die Erweiterung der Storage Access API um weitere Speicherarten gibt es derzeit nur in Chromium-Browsern (ab Version 125). Firefox und Safari unterstützen StorageAccessHandle noch nicht. Eine Feature-Erkennung und ein Rückfall auf den partitionierten Speicher sind deshalb Pflicht.
  • Datenschutz: Nicht partitionierter Speicher ermöglicht Tracking über mehrere Websites hinweg. Fordere den Zugriff nur an, wenn er wirklich nötig ist, und erkläre der Person vorher, wofür du ihn brauchst.