Signatur
Beschreibung
FileSystemDirectoryEntry ist ein Interface der File and Directory Entries API und steht für ein Verzeichnis. Es erbt von FileSystemEntry und damit die Eigenschaften name, fullPath, filesystem, isFile (immer false) und isDirectory (immer true).
Solche Objekte bekommt man in der Praxis fast nur auf zwei Wegen: Wenn der Nutzer Ordner per Drag & Drop ablegt, liefert DataTransferItem.webkitGetAsEntry() sie. Bei einem <input type="file" webkitdirectory> kommen sie über HTMLInputElement.webkitEntries. Einen Konstruktor gibt es nicht, und man kann auch nicht beliebig auf das lokale Dateisystem zugreifen. Die API ist nur lesend.
Die wichtigsten Methoden:
createReader(): gibt einenFileSystemDirectoryReaderzurück, mit dem man die Einträge des Verzeichnisses auflistet.getFile(path, options, successCallback, errorCallback): holt einenFileSystemFileEntryüber einen relativen oder absoluten Pfad.getDirectory(path, options, successCallback, errorCallback): holt einen untergeordnetenFileSystemDirectoryEntry.
Die API arbeitet mit Callbacks statt mit Promises. In modernem Code verpackt man die Aufrufe deshalb meist in Promises, damit man async/await nutzen kann. Für neue Anwendungen, die Dateien auch schreiben sollen, gibt es die File System Access API (FileSystemDirectoryHandle).
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $path | string | Bei getFile()/getDirectory(): Pfad zum gesuchten Eintrag, relativ zu diesem Verzeichnis oder absolut innerhalb des Dateisystems. |
|
| $options | { create?: boolean, exclusive?: boolean } | {} | Optionen für getFile()/getDirectory(). create: true führt in Browsern zu einem SecurityError, weil das Dateisystem nur gelesen werden kann. |
| $successCallback | (entry: FileSystemEntry) => void | Wird mit dem gefundenen FileSystemFileEntry bzw. FileSystemDirectoryEntry aufgerufen. |
|
| $errorCallback | (error: DOMException) => void | Wird im Fehlerfall aufgerufen, z. B. mit NotFoundError oder TypeMismatchError. |
Rückgabewert
createReader() gibt einen FileSystemDirectoryReader zurück. getFile() und getDirectory() geben undefined zurück und liefern ihr Ergebnis über die Callbacks.Beispiele
Abgelegten Ordner per Drag & Drop erkennen
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?.isDirectory) {
// entry ist ein FileSystemDirectoryEntry
console.log(`Ordner: ${entry.name} (${entry.fullPath})`);
} else if (entry?.isFile) {
console.log(`Datei: ${entry.name}`);
}
}
});
Ordnerinhalt vollständig und rekursiv auflisten (Promise-Wrapper)
// readEntries() liefert die Einträge in Blöcken und muss wiederholt
// aufgerufen werden, bis ein leeres Array kommt
const readAllEntries = (dirEntry) => new Promise((resolve, reject) => {
const reader = dirEntry.createReader();
const all = [];
const readBatch = () => {
reader.readEntries((batch) => {
if (batch.length === 0) return resolve(all);
all.push(...batch);
readBatch();
}, reject);
};
readBatch();
});
const entryToFile = (fileEntry) =>
new Promise((resolve, reject) => fileEntry.file(resolve, reject));
const collectFiles = async (dirEntry) => {
const files = [];
for (const entry of await readAllEntries(dirEntry)) {
if (entry.isDirectory) {
files.push(...await collectFiles(entry));
} else {
const file = await entryToFile(entry);
files.push({ path: entry.fullPath, size: file.size });
}
}
return files;
};
// Nutzung im drop-Handler:
// const files = await collectFiles(item.webkitGetAsEntry());
// console.table(files);
Gezielt eine Datei im Ordner über getFile() holen
const readPackageJson = (dirEntry) => new Promise((resolve, reject) => {
dirEntry.getFile('package.json', {}, (fileEntry) => {
fileEntry.file(async (file) => resolve(JSON.parse(await file.text())), reject);
}, reject);
});
// Im drop-Handler:
// try {
// const pkg = await readPackageJson(entry);
// console.log(`Projekt: ${pkg.name}`);
// } catch (err) {
// console.warn('Keine package.json gefunden:', err.name);
// }
Unterverzeichnis mit getDirectory() öffnen
const getSubDir = (dirEntry, name) => new Promise((resolve, reject) =>
dirEntry.getDirectory(name, {}, resolve, reject));
// const srcDir = await getSubDir(entry, 'src');
// console.log(srcDir.isDirectory, srcDir.fullPath);
// Wichtig · Fallstricke
- readEntries() liefert Blöcke: Chrome gibt pro Aufruf höchstens etwa 100 Einträge zurück. Man muss
readEntries()auf demselben Reader so lange erneut aufrufen, bis ein leeres Array kommt. Sonst fehlen Dateien, und das fällt oft nicht auf. - Nur Lesezugriff: Mit
{ create: true }kann man nichts anlegen, der Aufruf scheitert mit einem Fehler. Zum Schreiben braucht man die File System Access API (showDirectoryPicker(),FileSystemDirectoryHandle). - Zeitpunkt im Drop-Handler:
webkitGetAsEntry()muss man synchron imdrop-Event aufrufen. Nach einemawaitist dieDataTransferItemListleer. Deshalb zuerst alle Einträge einsammeln und danach asynchron verarbeiten. - Nur Callbacks: Die API kennt keine Promises. Wenn man den
errorCallbackweglässt, gehen Fehler wieNotFoundErrorunbemerkt verloren. - Kompatibilität: Wird von allen modernen Browsern unterstützt. Die Einstiegspunkte tragen aber historisch das Präfix
webkit(webkitGetAsEntry,webkitEntries). Die veralteten MethodenremoveRecursively()und das ältereDirectoryEntryaus der verworfenen FileSystem-API sollte man nicht verwenden. - Sicherheit: Man bekommt nur Zugriff auf Ordner, die der Nutzer selbst bereitgestellt hat. Dateinamen und Pfade kommen vom Nutzer und dürfen nicht ungefiltert per
innerHTMLausgegeben werden (XSS-Gefahr).