Signatur
Beschreibung
Das Interface FileSystemDirectoryReader gehört zur File and Directory Entries API. Ein Objekt davon bekommen Sie über FileSystemDirectoryEntry.createReader(). Damit können Sie den Inhalt eines Verzeichnisses auflisten. Jeder Eintrag ist entweder eine Datei (FileSystemFileEntry) oder ein Unterverzeichnis (FileSystemDirectoryEntry).
Typischerweise nutzen Sie das Interface beim Drag & Drop ganzer Ordner (über DataTransferItem.webkitGetAsEntry()) oder bei einem <input type="file" webkitdirectory>. So können Sie Ordnerstrukturen rekursiv durchlaufen, zum Beispiel für einen Upload, der die Verzeichnisstruktur beibehält.
Das Interface hat nur eine Methode: readEntries(successCallback, errorCallback). Wichtig ist: Ein einzelner Aufruf liefert nicht unbedingt alle Einträge. Chrome gibt zum Beispiel höchstens 100 Einträge pro Aufruf zurück. Sie müssen readEntries() deshalb so oft aufrufen, bis ein leeres Array zurückkommt.
Die API arbeitet mit Callbacks und nicht mit Promises. In der Praxis verpackt man readEntries() meist in ein Promise, damit man async/await nutzen kann.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $successCallback Pflicht | (entries: FileSystemEntry[]) => void | Parameter von readEntries(): Wird mit einem Array der nächsten Einträge aufgerufen. Ein leeres Array bedeutet, dass alle Einträge gelesen wurden. |
|
| $errorCallback | (error: DOMException) => void | Parameter von readEntries(): Wird bei einem Fehler aufgerufen, z. B. wenn das Lesen des Verzeichnisses fehlschlägt (NotFoundError, SecurityError). |
Beispiele
Reader erzeugen und einen Ordner per Drag & Drop einlesen
const dropZone = document.querySelector('#drop-zone');
dropZone.addEventListener('dragover', (e) => e.preventDefault());
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
const entry = e.dataTransfer.items[0]?.webkitGetAsEntry();
if (!entry?.isDirectory) return;
// FileSystemDirectoryReader erzeugen
const reader = entry.createReader();
reader.readEntries(
(entries) => {
for (const item of entries) {
console.log(item.isDirectory ? '📁' : '📄', item.name);
}
},
(err) => console.error('Lesefehler:', err.name)
);
});
Alle Einträge vollständig lesen (Promise-Wrapper mit Schleife)
const readBatch = (reader) =>
new Promise((resolve, reject) => reader.readEntries(resolve, reject));
const readAllEntries = async (dirEntry) => {
const reader = dirEntry.createReader();
const all = [];
let batch;
// So lange lesen, bis ein leeres Array kommt (Chrome: max. 100 pro Aufruf)
do {
batch = await readBatch(reader);
all.push(...batch);
} while (batch.length > 0);
return all;
};
// Verwendung im drop-Handler:
// const entries = await readAllEntries(entry);
// console.log(`${entries.length} Einträge gefunden`);
Ordnerstruktur rekursiv in File-Objekte umwandeln
const readBatch = (reader) =>
new Promise((resolve, reject) => reader.readEntries(resolve, reject));
const getFile = (fileEntry) =>
new Promise((resolve, reject) => fileEntry.file(resolve, reject));
const collectFiles = async (entry) => {
if (entry.isFile) {
const file = await getFile(entry);
return [{ path: entry.fullPath, file }];
}
const reader = entry.createReader();
const result = [];
let batch;
do {
batch = await readBatch(reader);
for (const child of batch) {
result.push(...(await collectFiles(child)));
}
} while (batch.length > 0);
return result;
};
document.querySelector('#drop-zone').addEventListener('drop', async (e) => {
e.preventDefault();
const root = e.dataTransfer.items[0].webkitGetAsEntry();
const files = await collectFiles(root);
files.forEach(({ path, file }) => console.log(path, file.size));
});
// Wichtig · Fallstricke
- Häufigster Fehler:
readEntries()nur einmal aufrufen. Dann fehlen bei großen Ordnern Einträge, weil Chrome/Edge höchstens 100 pro Aufruf liefern. Rufen Sie die Methode immer so lange auf, bis ein leeres Array zurückkommt. - Rufen Sie
readEntries()auf demselben Reader nicht parallel auf. Warten Sie auf jeden Callback, bevor Sie den nächsten Aufruf starten. Sonst gibt es einenInvalidStateError. - Greifen Sie im
drop-Handler synchron aufdataTransfer.itemsundwebkitGetAsEntry()zu. Nach dem erstenawaitist die DataTransfer-Liste leer. - Die API ist inzwischen in allen modernen Browsern verfügbar. Der Einstiegspunkt
webkitGetAsEntry()hat aber aus historischen Gründen noch das Präfix. Die veraltete VarianterequestFileSystem()gibt es nur in Chromium, und sie ist nicht standardisiert. - Die Einträge sind schreibgeschützt. Für Lese- und Schreibzugriff auf echte Verzeichnisse ist die neuere File System Access API (
FileSystemDirectoryHandle,showDirectoryPicker()) gedacht. Sie bietet Promises und asynchrone Iteratoren, wird aber nicht von allen Browsern unterstützt. - Die Reihenfolge der Einträge ist nicht festgelegt. Sortieren Sie bei Bedarf selbst, z. B. nach
name.