Signatur
Beschreibung
FileSystemFileEntry gehört zur File and Directory Entries API und steht für eine einzelne Datei in einem (meist virtuellen) Dateisystem. Das Interface erbt von FileSystemEntry. Damit hat es die Eigenschaften name, fullPath, filesystem, isFile (immer true) und isDirectory (immer false) sowie die Methode getParent().
Du begegnest dem Interface vor allem bei Drag-and-drop von Dateien und Ordnern. DataTransferItem.webkitGetAsEntry() liefert einen Eintrag. Ist isFile gesetzt, hast du einen FileSystemFileEntry vor dir. Handelt es sich um einen FileSystemDirectoryEntry, kannst du ihn rekursiv durchlaufen. Auf diese Weise lassen sich ganze Ordnerstrukturen per Drag-and-drop hochladen. Einträge liefert auch HTMLInputElement.webkitEntries bei <input type="file" webkitdirectory>.
Die wichtigste Methode ist file(successCallback, errorCallback). Sie arbeitet asynchron und übergibt das zugehörige File-Objekt an den Callback. Dieses Objekt liest du dann mit file.text(), file.arrayBuffer() oder einem FileReader aus. Die veraltete Methode createWriter() wurde nie standardisiert und ist in modernen Browsern nicht verfügbar.
Die API arbeitet mit Callbacks und nicht mit Promises. In der Praxis verpackst du file() daher in ein Promise, um async/await nutzen zu können. Möchtest du im Dateisystem des Nutzers lesen und schreiben, ist die modernere File System Access API (FileSystemFileHandle) die bessere Wahl.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $successCallback Pflicht | (file: File) => void | Parameter von file(): Wird mit dem File-Objekt aufgerufen, das zu diesem Eintrag gehört. |
|
| $errorCallback | (error: DOMException) => void | Parameter von file(): Wird aufgerufen, wenn beim Erzeugen des File-Objekts ein Fehler auftritt, z. B. NotFoundError oder SecurityError. |
Rückgabewert
file() gibt selbst nichts zurück. Das Ergebnis kommt asynchron über successCallback bzw. errorCallback an.Beispiele
Gezogene Datei als FileSystemFileEntry auslesen
const dropZone = document.querySelector('#drop-zone');
dropZone.addEventListener('dragover', (e) => e.preventDefault());
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
for (const item of e.dataTransfer.items) {
const entry = item.webkitGetAsEntry();
if (entry?.isFile) {
// entry ist ein FileSystemFileEntry
entry.file(
(file) => console.log(`${entry.fullPath}: ${file.size} Bytes, Typ ${file.type}`),
(err) => console.error('Fehler beim Lesen:', err.name)
);
}
}
});
file() als Promise verpacken und mit async/await nutzen
const getFile = (fileEntry) =>
new Promise((resolve, reject) => fileEntry.file(resolve, reject));
const readEntryText = async (fileEntry) => {
const file = await getFile(fileEntry);
const text = await file.text();
console.log(`${fileEntry.name} enthält ${text.length} Zeichen`);
return text;
};
// Aufruf z. B. im drop-Handler:
// const entry = e.dataTransfer.items[0].webkitGetAsEntry();
// if (entry.isFile) await readEntryText(entry);
Ganzen Ordner rekursiv durchlaufen und alle Dateien sammeln
const getFile = (entry) => new Promise((res, rej) => entry.file(res, rej));
const readAllEntries = (dirEntry) => {
const reader = dirEntry.createReader();
const all = [];
// readEntries() liefert Einträge in Blöcken und muss wiederholt aufgerufen werden
return new Promise((resolve, reject) => {
const readBatch = () => reader.readEntries((batch) => {
if (batch.length === 0) return resolve(all);
all.push(...batch);
readBatch();
}, reject);
readBatch();
});
};
const collectFiles = async (entry, result = []) => {
if (entry.isFile) {
const file = await getFile(entry);
result.push({ path: entry.fullPath, file });
} else if (entry.isDirectory) {
for (const child of await readAllEntries(entry)) {
await collectFiles(child, result);
}
}
return result;
};
document.body.addEventListener('dragover', (e) => e.preventDefault());
document.body.addEventListener('drop', async (e) => {
e.preventDefault();
// Einträge synchron abholen, bevor das Event endet
const entries = [...e.dataTransfer.items].map((i) => i.webkitGetAsEntry()).filter(Boolean);
const files = [];
for (const entry of entries) await collectFiles(entry, files);
console.log(files.map((f) => f.path));
});
// Wichtig · Fallstricke
- Einträge sofort abholen:
webkitGetAsEntry()musst du synchron imdrop-Handler aufrufen. Nach einemawaitist dieDataTransferItemListleer. - Nur Callbacks:
file()gibt kein Promise zurück. Fürasync/awaitverpackst du den Aufruf selbst in ein Promise. createWriter()gibt es nicht mehr: Die Methode war nie Teil des Standards und ist in modernen Browsern entfernt. Mit dieser API kannst du Dateien nicht schreiben.- Präfix
webkit: Obwohl sie so heißen, werdenwebkitGetAsEntry()undwebkitEntriesvon allen modernen Browsern unterstützt, auch von Firefox. Eine unpräfixierte VariantegetAsEntry()gibt es praktisch nirgends. - Nur Lesezugriff auf freigegebene Daten: Die Einträge sind auf das virtuelle Dateisystem beschränkt, das der Nutzer per Drag-and-drop oder Dateiauswahl freigegeben hat. Andere Pfade im Dateisystem sind nicht erreichbar.
- Alternative: Brauchst du dauerhaften Lese- und Schreibzugriff, nimm die File System Access API (
FileSystemFileHandle,DataTransferItem.getAsFileSystemHandle()). Sie wird bisher aber vor allem von Chromium-Browsern unterstützt.