Start · Sprachen · JavaScript · Referenz · StorageManager

StorageManager

Schnittstelle

Das <code>StorageManager</code>-Interface der Storage API verwaltet Persistenzberechtigungen und schätzt den belegten und verfügbaren Speicher eines Origins ab.

seit JavaScript Baseline: alle modernen Browser (estimate/persiste Kategorie: webapi

Signatur

interface StorageManager

Beschreibung

Das StorageManager-Interface ist Teil des Storage Standard der WHATWG. Du erreichst es nicht über einen Konstruktor, sondern über die Singleton-Instanz navigator.storage (im Fenster- und im Worker-Kontext). Es fasst alle clientseitigen Speichermechanismen eines Origins zusammen: IndexedDB, Cache API, Service-Worker-Registrierungen und das Origin Private File System (OPFS).

Die wichtigsten Methoden:

  • estimate() – liefert ein Promise<StorageEstimate> mit usage (belegte Bytes) und quota (zulässige Bytes). So kannst du prüfen, ob noch Platz für große Downloads oder Offline-Daten da ist.
  • persist() – bittet den Browser, den Speicher des Origins als persistent zu markieren. Solcher Speicher wird bei Speicherknappheit nicht automatisch gelöscht. Rückgabewert: Promise<boolean>.
  • persisted() – prüft, ob schon persistenter Speicher gewährt wurde (Promise<boolean>).
  • getDirectory() – gibt ein Promise<FileSystemDirectoryHandle> auf das Wurzelverzeichnis des Origin Private File System zurück.

Du brauchst StorageManager vor allem in Offline-first-Anwendungen und PWAs, die viele Daten lokal ablegen (Medien, Kartenkacheln, Dokumente). Ohne Persistenz gilt der Speicher als best effort: Der Browser darf ihn bei Platzmangel nach einer LRU-Strategie ohne Rückfrage löschen.

Alle Methoden stehen nur in einem sicheren Kontext (HTTPS oder localhost) zur Verfügung und arbeiten asynchron.

Rückgabewert

Typ
StorageManager
Beschreibung
Zugriff über navigator.storage – eine Instanz pro Kontext (Fenster oder Worker). Es gibt keinen öffentlichen Konstruktor.

Beispiele

Belegten und verfügbaren Speicher anzeigen

const formatMB = (bytes) => `${(bytes / 1024 / 1024).toFixed(1)} MB`;

const zeigeSpeicher = async () => {
  if (!navigator.storage?.estimate) {
    console.warn('StorageManager.estimate() wird nicht unterstützt');
    return;
  }
  const { usage, quota } = await navigator.storage.estimate();
  const prozent = ((usage / quota) * 100).toFixed(2);
  console.log(`Belegt: ${formatMB(usage)} von ${formatMB(quota)} (${prozent} %)`);
};

zeigeSpeicher();
Belegt: 12.4 MB von 2048.0 MB (0.61 %)

Persistenten Speicher anfordern (PWA mit Offline-Daten)

const sichereSpeicher = async () => {
  if (!navigator.storage?.persist) return false;

  // Zuerst prüfen, ob schon persistenter Speicher gewährt wurde
  if (await navigator.storage.persisted()) {
    console.log('Speicher ist bereits persistent.');
    return true;
  }

  const gewaehrt = await navigator.storage.persist();
  console.log(gewaehrt
    ? 'Persistenter Speicher gewährt – Daten werden nicht automatisch gelöscht.'
    : 'Abgelehnt – Speicher bleibt "best effort".');
  return gewaehrt;
};

// Am besten nach einer Nutzeraktion aufrufen, z. B. "Offline verfügbar machen"
document.querySelector('#offline-btn')?.addEventListener('click', sichereSpeicher);
Persistenter Speicher gewährt – Daten werden nicht automatisch gelöscht.

Vor großem Download freien Platz prüfen

const hatGenugPlatz = async (benoetigteBytes) => {
  const { usage = 0, quota = 0 } = await navigator.storage.estimate();
  return quota - usage > benoetigteBytes * 1.1; // 10 % Puffer
};

const ladeOfflinePaket = async (url, groesse) => {
  if (!(await hatGenugPlatz(groesse))) {
    console.error('Nicht genug Speicher für das Offline-Paket.');
    return;
  }
  const cache = await caches.open('offline-v1');
  await cache.add(url);
  console.log('Paket gespeichert.');
};

ladeOfflinePaket('/karten/region-nord.pbf', 50 * 1024 * 1024);
Paket gespeichert.

Datei im Origin Private File System (OPFS) anlegen

const speichereNotiz = async (text) => {
  const root = await navigator.storage.getDirectory();
  const datei = await root.getFileHandle('notiz.txt', { create: true });
  const writable = await datei.createWritable();
  await writable.write(text);
  await writable.close();

  const inhalt = await (await datei.getFile()).text();
  console.log('Gelesen:', inhalt);
};

speichereNotiz('Einkaufsliste: Milch, Brot');
Gelesen: Einkaufsliste: Milch, Brot

// Wichtig · Fallstricke

  • Nur Schätzwerte: estimate() liefert absichtlich ungenaue Werte (z. B. durch Padding bei opaken Cache-Antworten), damit Origins keine Daten über andere Origins oder das System ausspähen können. quota ist nicht der freie Festplattenplatz.
  • Nur sicherer Kontext: navigator.storage gibt es nur unter HTTPS oder localhost. Prüfe die Unterstützung vorher, z. B. mit navigator.storage?.persist.
  • persist() je nach Browser: Chromium entscheidet nach Heuristiken (Engagement, Lesezeichen, installierte PWA, Benachrichtigungsberechtigung) und zeigt keinen Dialog. Firefox fragt den Nutzer mit einem Dialog. Safari gewährt Persistenz nur eingeschränkt. Rechne immer damit, dass false zurückkommt.
  • Safari/ITP: Ohne Persistenz kann Safari Skript-schreibbaren Speicher nach 7 Tagen ohne Nutzerinteraktion löschen.
  • Auch persistenter Speicher lässt sich vom Nutzer löschen, etwa über die Browsereinstellungen. Sichere wichtige Daten deshalb zusätzlich auf dem Server.
  • Das nicht standardisierte Feld usageDetails in StorageEstimate gibt es nur in Chromium. Verlass dich nicht darauf.
  • Wird die Quote überschritten, werfen Schreibvorgänge einen QuotaExceededError (DOMException). Fang diesen Fehler ab.