Signatur
Beschreibung
Die Methode showOpenFilePicker() gehört zur File System Access API. Sie zeigt den Dateiauswahldialog des Betriebssystems an und gibt statt reiner File-Objekte (wie bei <input type="file">) Handles vom Typ FileSystemFileHandle zurück. Über ein solches Handle liest man die Datei mit getFile() und kann sie nach Erteilung der Berechtigung mit createWritable() auch direkt überschreiben.
Gedacht ist die Methode für Web-Anwendungen, die sich wie Desktop-Programme verhalten sollen: Editoren, Bild- und Grafikwerkzeuge oder IDEs, die eine Datei öffnen, bearbeiten und an derselben Stelle wieder speichern. Handles lassen sich zudem in IndexedDB ablegen, damit man zuletzt geöffnete Dateien später erneut öffnen kann (die Berechtigung muss dann meist erneut bestätigt werden).
Wichtig: Der Aufruf braucht eine vorübergehende Benutzeraktivierung (z. B. einen Klick), funktioniert nur in einem sicheren Kontext (HTTPS oder localhost) und nicht in plattformübergreifenden (cross-origin) iframes. Bricht der Nutzer den Dialog ab, wird das Promise mit einer AbortError-DOMException zurückgewiesen. Das sollte man immer abfangen.
Rückgabewert
FileSystemFileHandle-Objekten erfüllt wird. Das Array ist auch ohne multiple immer ein Array (dann mit genau einem Eintrag). Es wird mit AbortError (Abbruch), SecurityError (unsicherer Kontext, cross-origin iframe, keine Benutzeraktivierung) oder TypeError (ungültige types) zurückgewiesen.Beispiele
Textdatei öffnen und Inhalt anzeigen
const button = document.querySelector('#open');
const editor = document.querySelector('#editor');
button.addEventListener('click', async () => {
try {
const [handle] = await window.showOpenFilePicker({
types: [{
description: 'Textdateien',
accept: { 'text/plain': ['.txt', '.md'] }
}],
excludeAcceptAllOption: true
});
const file = await handle.getFile();
editor.value = await file.text();
console.log(`Geöffnet: ${file.name} (${file.size} Bytes)`);
} catch (err) {
if (err.name === 'AbortError') return; // Nutzer hat abgebrochen
console.error('Fehler beim Öffnen:', err);
}
});
Mehrere Bilder auswählen, mit Fallback auf <input type="file">
const pickImages = async () => {
if (!('showOpenFilePicker' in window)) {
// Fallback für Firefox/Safari
return new Promise((resolve) => {
const input = Object.assign(document.createElement('input'), {
type: 'file', accept: 'image/*', multiple: true
});
input.addEventListener('change', () => resolve([...input.files]));
input.click();
});
}
const handles = await window.showOpenFilePicker({
multiple: true,
id: 'bilder',
startIn: 'pictures',
types: [{ description: 'Bilder', accept: { 'image/*': ['.png', '.jpg', '.jpeg', '.webp'] } }]
});
return Promise.all(handles.map((h) => h.getFile()));
};
document.querySelector('#pick').addEventListener('click', async () => {
const files = await pickImages();
console.log(files.map((f) => f.name));
});
Geöffnete Datei direkt überschreiben
let fileHandle;
document.querySelector('#open').addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
document.querySelector('#editor').value = await file.text();
});
document.querySelector('#save').addEventListener('click', async () => {
const opts = { mode: 'readwrite' };
if ((await fileHandle.queryPermission(opts)) !== 'granted' &&
(await fileHandle.requestPermission(opts)) !== 'granted') {
console.warn('Keine Schreibberechtigung');
return;
}
const writable = await fileHandle.createWritable();
await writable.write(document.querySelector('#editor').value);
await writable.close(); // erst hier wird auf die Platte geschrieben
console.log('Gespeichert');
});
// Wichtig · Fallstricke
- Browser-Unterstützung: Nur in Chromium-Browsern auf dem Desktop (Chrome/Edge 86+, Opera). Firefox und Safari unterstützen die Methode nicht, auf Android fehlt sie ebenfalls. Vorher immer mit
'showOpenFilePicker' in windowprüfen und auf<input type="file">ausweichen. - Benutzeraktivierung nötig: Ein Aufruf ohne vorherige Nutzerinteraktion, etwa beim Laden der Seite oder nach langen
await-Ketten, scheitert mitSecurityError. - Abbruch ist kein Fehler: Schließt der Nutzer den Dialog, wird das Promise mit
AbortErrorzurückgewiesen. Diesen Fall gesondert behandeln und keine Fehlermeldung zeigen. - Nur Lesezugriff zu Beginn: Das Handle hat zunächst nur Leserechte. Zum Schreiben ist
requestPermission({ mode: 'readwrite' })nötig, was eine weitere Rückfrage auslösen kann. - Sicherheit: Nur in sicheren Kontexten (HTTPS) und nicht in cross-origin iframes verfügbar. Systemordner und sensible Dateien kann der Browser sperren. Inhalte aus gewählten Dateien nie ungeprüft per
innerHTMLeinfügen, sonst droht XSS. - Die Methode liefert immer ein Array. Die Destrukturierung
const [handle] = …ist deshalb die übliche Schreibweise.