Signatur
Beschreibung
Die Eigenschaft files des LaunchParams-Interfaces enthält alle Dateien, die beim Start einer installierten Progressive Web App (PWA) übergeben wurden. Das passiert zum Beispiel, wenn jemand im Dateimanager des Betriebssystems eine Datei per „Öffnen mit …“ an die App übergibt oder eine Datei auf das App-Symbol zieht. Jeder Eintrag ist ein FileSystemHandle, in der Praxis meist ein FileSystemFileHandle.
Welche Dateitypen die App annimmt, legst du im Web-App-Manifest im Feld file_handlers fest (Ziel-URL action und accept mit MIME-Typen und Dateiendungen). An das LaunchParams-Objekt kommst du nur über window.launchQueue.setConsumer(): Die Callback-Funktion bekommt für jeden Start ein LaunchParams-Objekt, und dessen files liest du dann aus.
Weil es Handles der File System API sind, kannst du mit getFile() den Inhalt lesen. Hat der Nutzer Schreibrechte erteilt, kannst du mit createWritable() auch direkt in die Originaldatei zurückschreiben. So lassen sich echte Desktop-Editoren bauen.
Rückgabewert
FileSystemHandle-Objekten, meist FileSystemFileHandle. Ohne übergebene Dateien ist es leer, etwa bei einem normalen Start über das App-Symbol.Beispiele
Gestartete Dateien auflisten
if ('launchQueue' in window) {
window.launchQueue.setConsumer((launchParams) => {
if (!launchParams.files.length) return; // normaler Start ohne Datei
for (const handle of launchParams.files) {
console.log(`${handle.kind}: ${handle.name}`);
}
});
} else {
console.warn('File Handling API wird nicht unterstützt.');
}
Textdatei in einen Editor laden
const editor = document.querySelector('#editor');
let currentHandle = null;
window.launchQueue?.setConsumer(async ({ files }) => {
const [handle] = files;
if (!handle || handle.kind !== 'file') return;
currentHandle = handle;
const file = await handle.getFile();
editor.value = await file.text();
document.title = `${file.name} – MeinEditor`;
});
Änderungen in die Originaldatei zurückschreiben
const saveFile = async (handle, content) => {
// Schreibrecht prüfen bzw. anfragen
const opts = { mode: 'readwrite' };
if ((await handle.queryPermission(opts)) !== 'granted' &&
(await handle.requestPermission(opts)) !== 'granted') {
throw new Error('Kein Schreibzugriff erteilt');
}
const writable = await handle.createWritable();
await writable.write(content);
await writable.close();
};
document.querySelector('#save').addEventListener('click', () =>
saveFile(currentHandle, editor.value).then(() => console.log('Gespeichert'))
);
Passender Manifest-Eintrag (manifest.webmanifest)
const manifest = {
name: 'MeinEditor',
start_url: '/',
display: 'standalone',
file_handlers: [
{
action: '/open',
accept: { 'text/plain': ['.txt', '.md'] }
}
]
};
console.log(JSON.stringify(manifest, null, 2));
// Wichtig · Fallstricke
- Experimentell und nur in Chromium: Seit Chrome/Edge 102 auf dem Desktop verfügbar. Firefox und Safari unterstützen das nicht. Prüfe deshalb immer vorher mit
'launchQueue' in window. - Nur bei installierten PWAs:
filesist nur gefüllt, wenn die App installiert ist, einen gültigenfile_handlers-Eintrag im Manifest hat und über eine Datei gestartet wurde. In einem normalen Browser-Tab bleibt das Array leer. - Consumer früh registrieren: Rufe
setConsumer()möglichst früh beim Laden der Seite auf. Bis dahin werden Startvorgänge in der Warteschlange gesammelt und danach nachgeliefert. Wenn die App schon offen ist, kann der Callback mehrfach aufgerufen werden. - Berechtigungen: Lesen ist erlaubt, Schreiben braucht in der Regel eine ausdrückliche Zustimmung über
requestPermission({ mode: 'readwrite' }). Diese Anfrage verlangt eine Nutzeraktion, zum Beispiel einen Klick. - Nicht vertrauenswürdige Inhalte: Dateiinhalte immer als unsicher behandeln. Nicht ungeprüft per
innerHTMLeinfügen (XSS-Gefahr), bessertextContentodervalueverwenden. - Das Array ist schreibgeschützt. Handles lassen sich aber in IndexedDB speichern, damit die App die Datei beim nächsten Start wieder öffnen kann.