Service Worker für Offline-Dateitransfer-Caching
Nutzen Sie Service Worker, um Offline-Dateiübertragung zu ermöglichen: Cache-Strategien, Background Sync und PWA-Patterns im Überblick.
Das BSI empfiehlt in seinen Mindestanforderungen an Webanwendungen explizit die Entkopplung von Netzwerkverfügbarkeit und Anwendungsfunktionalität — Service Worker sind die technische Umsetzung dieses Prinzips für Dateiübertragungs-Apps. Ein Service Worker lässt eine Transfer-App auch bei Netzwerkausfall funktionieren: das HTML-Shell und JavaScript werden mit der Cache-API gecacht, fehlgeschlagene Uploads werden mit der Background-Sync-API eingereiht, partielle Chunks in IndexedDB gespeichert, und alles wird bei Rückkehr der Verbindung wiederholt.
Der Worker läuft auf einem separaten Thread mit eigenem Event-Loop, fängt fetch-Ereignisse für seinen Gültigkeitsbereich ab und überlebt Tab-Schließungen. Für Upload-Tools ist das richtige Rezept: Stale-While-Revalidate für die App-Shell, IndexedDB-gestütztes Chunk-Queuing für laufende Übertragungen und eine periodische Background-Sync-Registrierung, die Uploads alle 15 Minuten wiederholt, bis sie erfolgreich sind.
Was Service Worker für Transfer-Apps tatsächlich bringen
Der große Gewinn: navigator.serviceWorker überlebt Tab-Neuladen, Offline-Phasen und sogar den Ruhezustand des Telefons. Wenn ein Nutzer einen 2-GB-Upload auf unsicherem Zug-WLAN startet, sollen bereits erfolgreich übertragene Chunks erfolgreich bleiben, laufende Chunks bei Wiederbandbreite erneut gesendet werden, und der Gesamtzustand auch dann wiederherstellbar sein, wenn der Browser den Tab zur Speicherrückgewinnung beendet. Ein Service Worker — der unabhängig von einem bestimmten Tab läuft — ist das Stück, das all das ermöglicht.
Die API bietet drei Bausteine: Cache zum Speichern von Antworten nach URL, IndexedDB für strukturierte Daten (Chunk-Queues, Session-Zustand) und SyncManager zum Einplanen von Wiederholungen, die ausgelöst werden, wenn das Gerät online ist.
Den Worker registrieren und versionieren
Einmalig beim App-Start registrieren und Updates explizit behandeln:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js', { scope: '/' })
.then((reg) => reg.addEventListener('updatefound', () => {
const sw = reg.installing;
sw.addEventListener('statechange', () => {
if (sw.state === 'installed' && navigator.serviceWorker.controller) {
// neue Version bereit, Nutzer zum Aktualisieren auffordern
}
});
}));
}
Cache-Keys versionieren (transfer-v7), damit ein neues Deploy alte Assets ungültig macht, ohne veraltetes JavaScript zurückzulassen. Der klassische Bug: index.html bleibt ewig gecacht, Nutzer bekommen nie das Update, und Sie debuggen wochenlang über Slack. Caches an Build-Hashes binden und im activate-Event aufräumen.
Caching-Strategien für App-Shell vs. Nutzerdaten
Verschiedene Ressourcen verdienen verschiedene Strategien:
- App-Shell (HTML, CSS, JS, Icons): Cache-First mit Netzwerk-Fallback. Sofortige Ladezeiten, funktioniert offline.
- API-Metadaten (
/shares/:id): Network-First mit Cache-Fallback, 60-Sekunden-TTL. Frisch wenn online, nutzbar wenn nicht. - Datei-Bytes: niemals cachen. Dateien sind oft Gigabyte groß, und die Cache-API hat Origin-Quoten (typischerweise 60 % des freien Speichers).
- Schriften von CDNs: Stale-While-Revalidate. Schnell und automatisch aktualisierend.
Im fetch-Handler:
self.addEventListener('fetch', (e) => {
const url = new URL(e.request.url);
if (url.pathname.startsWith('/assets/')) {
e.respondWith(cacheFirst(e.request, 'shell-v7'));
} else if (url.pathname.startsWith('/api/shares/')) {
e.respondWith(networkFirst(e.request, 'api-v1', 60));
}
});
Niemals Anfragen für binäre Datei-Uploads abfangen — umleiten, indem Sie auf e.request.method === 'PUT' prüfen und frühzeitig zurückgeben. Gigabyte-PUTs durch den Worker zu proxyen ist eine Speicher-Katastrophe.
Fehlgeschlagene Uploads mit Background Sync einreihen
SyncManager ist der Schlüssel zu belastbaren Uploads. Wenn ein Chunk-PUT scheitert, in IndexedDB speichern und einen Sync registrieren:
// im Seiten-Code
const reg = await navigator.serviceWorker.ready;
await reg.sync.register('flush-uploads');
// in sw.js
self.addEventListener('sync', (event) => {
if (event.tag === 'flush-uploads') {
event.waitUntil(flushPendingUploads());
}
});
Der Browser löst das sync-Ereignis aus, sobald Netzwerk zurückkehrt, mit exponentiellem Backoff bis zu ~24 Stunden. Chrome und Edge unterstützen es; Safari lieferte eine Teilmenge in 17.5 unter dem „Background Fetch"-Flag, erfordert aber Nutzererlaubnis. Für Safari auf erneuten Versuch beim nächsten sichtbaren Seitenaufruf via visibilitychange zurückfallen.
Die Background Fetch API ist ein separates Werkzeug speziell für große Dateioperationen — sie zeigt eine persistente Benachrichtigung in der Browser-Oberfläche, damit Nutzer den Fortschritt auch nach dem Schließen des Tabs verfolgen können. Empfehlenswert für Uploads über 500 MB.
Partielle Uploads in IndexedDB speichern
IndexedDB ist Ihr dauerhafter Scratch-Bereich. Eine kleine Datenbank einmal öffnen, dann Session-Metadaten plus Chunk-Offsets speichern:
const db = await openDB('transfers', 1, {
upgrade(db) {
db.createObjectStore('sessions', { keyPath: 'id' });
db.createObjectStore('chunks', { keyPath: ['sessionId', 'index'] });
}
});
await db.put('sessions', {
id, fileName, fileSize, fileFingerprint, createdAt: Date.now(),
completedIndexes: [], partUrls
});
Keine rohen Chunk-Bytes speichern — sie kommen aus dem File-Handle, das IndexedDB als strukturierte Clone-Referenz persistieren kann, die über Neuladen hinweg gültig bleibt. Das Handle zu speichern vermeidet das Duplizieren von 2 GB Bytes in der Datenbank.
Origin-Speicher hat Grenzen: etwa 60 % des freien Speichers auf Desktop-Chrome, 1 GB pro Origin auf iOS Safari vor dem Eviction-Druck. navigator.storage.persist() anfordern, um den „persistenten" Bucket zu bekommen, den Browser nicht automatisch löschen.
Offline- und Online-Übergänge handhaben
Auf online- und offline-Ereignisse lauschen, sowohl auf der Seite als auch im Service Worker:
// Seite
window.addEventListener('online', () => {
ui.showBanner('Wieder online — Uploads werden fortgesetzt');
navigator.serviceWorker.controller?.postMessage({ type: 'resume' });
});
window.addEventListener('offline', () => {
ui.showBanner('Offline — Uploads pausiert');
});
navigator.onLine ist bei Corporate-Captive-Portalen notorisch unzuverlässig — es meldet true, wenn das Gerät eine lokale Netzwerkverbindung hat, aber kein Internet. Für verlässliche Erkennung ein kleines fetch('/ping', { cache: 'no-store' }) mit 3-Sekunden-Timeout durchführen.
Es zu einer richtigen PWA machen
Eine manifest.json mit display: standalone, einem Icon-Set und start_url: / ausliefern. apple-touch-icon-Links für iOS hinzufügen. Dateihandhabung deklarieren, damit das Betriebssystem die App mit bestimmten Erweiterungen verknüpfen kann:
{
"name": "Hex Transfer",
"file_handlers": [{
"action": "/share-target",
"accept": { "application/*": [".pdf", ".zip", ".docx"] }
}]
}
In Kombination mit Web Share Target können Nutzer Dateien direkt aus dem OS-Teilen-Menü in die App schicken. Auf Chrome Android und Desktop-Chromium kann die PWA als Standard-Handler für die deklarierten Dateitypen registriert werden — das verwandelt eine Browser-Seite in eine App, die sich wie ein natives Upload-Werkzeug verhält.
Die Offline-Geschichte testen
Drei Szenarien manuell testen, da automatisierte Offline-Tests fehleranfällig sind:
- Einen 500-MB-Upload auf schnellem WLAN starten, bei 30 % in den Flugzeugmodus wechseln, 30 Sekunden warten, WLAN wieder einschalten. Der Upload sollte ohne Nutzeraktion von dort fortgesetzt werden, wo er gestoppt hat.
- Einen Upload starten, bei 60 % den Tab schließen, 2 Minuten warten, neu öffnen. Die Session zur Fortsetzung anbieten.
- Einen Upload auf dem Mobiltelefon starten, den Bildschirm 5 Minuten sperren. Background Sync sollte beim Entsperren auslösen und die Übertragung abschließen.
Chrome DevTools' „Offline"-Checkbox und Application > Service Workers > Update on reload sind unverzichtbar. Das „Drosselungs"-Profil im Netzwerk-Panel ermöglicht die Simulation von Fast 3G und Slow 3G, um zu sehen, wie die Fehler-UI reagiert.
HexaTransfer setzt einen Service Worker für App-Shell-Caching und IndexedDB für laufende Session-Zustände ein, damit Neuladen und kurze Offline-Phasen den Upload-Fortschritt nicht verlieren. Testen Sie es unter https://hexatransfer.com — kostenlos, kein Konto, bis 10 GB.
Fallstricke, die man kennen sollte
Service Worker haben eine kleine Sammlung von Stolperfallen: Sie funktionieren nur auf HTTPS (außer localhost), Cache-Quoten variieren stark zwischen Browsern, iOS Safari weckt Worker für Background Sync nicht zuverlässig auf, DevTools können veraltete Worker aggressiv zwischenspeichern (während der Entwicklung immer „Bypass for network" aktivieren), und importScripts läuft synchron während der Installation — daher niemals langsame Drittanbieter-Skripte dort abrufen. Einen kleinen Integrationstest schreiben, der prüft, ob der Worker aktiviert wird, Clients beansprucht und die Offline-Seite ausliefert — dieser eine Test fängt 80 % der Regressionen, die in der Produktion auftreten werden.
Große Dateien sicher mit Ende-zu-Ende-Verschlüsselung senden
Übertragen Sie Dateien bis zu 10 GB kostenlos mit Ende-zu-Ende-Verschlüsselung. Kein Konto erforderlich. Ihre Dateien werden in Ihrem Browser verschlüsselt, bevor sie hochgeladen werden — niemand sonst kann sie lesen.
Datei senden