Signatur
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
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);
}
});
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() });
});
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 });
});
// Wichtig · Fallstricke
- Nur mit ausdrücklicher Anforderung: Wurde
requestStorageAccess()ohnegetDirectory: true(oderall: true) aufgerufen, wird das Promise mit einerDOMExceptionabgelehnt. Wer ohne Argument aufruft, bekommt nur Zugriff auf Cookies und keinenStorageAccessHandle. - Nutzeraktion nötig:
requestStorageAccess()braucht in der Regel eine vorübergehende Nutzeraktion, zum Beispiel einen Klick. Außerdem muss das iframe die Erlaubnisstorage-accesshaben, bei Sandbox-iframes überallow-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 ausgetDirectory()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
StorageAccessHandlenoch 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.