Signatur
Beschreibung
Die Schnittstelle FileSystem gehört zum File and Directory Entries API und steht für ein Dateisystem, in dem die zugehörigen FileSystemEntry-Objekte liegen. Selbst erzeugt man sie nicht. Man bekommt sie über die Eigenschaft filesystem eines Eintrags, meist wenn Nutzer Dateien oder Ordner per Drag & Drop ablegen (DataTransferItem.webkitGetAsEntry()) oder über ein <input type="file" webkitdirectory> auswählen (HTMLInputElement.webkitEntries).
Die Schnittstelle hat nur zwei schreibgeschützte Eigenschaften:
FileSystem.name: einstringmit einem vom Browser vergebenen, eindeutigen Namen des Dateisystems.FileSystem.root: einFileSystemDirectoryEntry, der das Wurzelverzeichnis darstellt. Von dort aus kann man mitcreateReader(),getFile()undgetDirectory()durch die Struktur gehen.
Praktisch nutzt man FileSystem vor allem, um abgelegte Ordner rekursiv zu durchlaufen, etwa für Upload-Funktionen, die ganze Verzeichnisbäume samt relativer Pfade übernehmen sollen. Die Dateisysteme, die man so erhält, sind nur lesbar und zeigen nur die Dateien, die der Nutzer freigegeben hat.
Rückgabewert
FileSystemEntry.filesystem. Sie hat die Eigenschaften name (string) und root (FileSystemDirectoryEntry).Beispiele
FileSystem aus einem Drag-&-Drop-Eintrag lesen
const dropZone = document.querySelector('#drop-zone');
dropZone.addEventListener('dragover', (event) => event.preventDefault());
dropZone.addEventListener('drop', (event) => {
event.preventDefault();
// Einträge synchron im Handler holen, danach ist DataTransfer leer
for (const item of event.dataTransfer.items) {
const entry = item.webkitGetAsEntry();
if (!entry) continue;
const fs = entry.filesystem;
console.log('Dateisystem:', fs.name);
console.log('Wurzel:', fs.root.fullPath);
console.log('Eintrag:', entry.fullPath, entry.isDirectory ? '(Ordner)' : '(Datei)');
}
});
Wurzelverzeichnis vollständig auslesen (readEntries in Schleife)
// readEntries liefert Ergebnisse in Teilen, also so lange aufrufen, 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 listRoot = async (fileSystem) => {
const entries = await readAllEntries(fileSystem.root);
entries.forEach((e) => console.log(e.isFile ? '📄' : '📁', e.fullPath));
};
// Nutzung, z. B. im drop-Handler: listRoot(entry.filesystem);
Ordnerbaum rekursiv in File-Objekte umwandeln
const getFile = (fileEntry) => new Promise((res, rej) => fileEntry.file(res, rej));
const readDir = (dirEntry) => new Promise((resolve, reject) => {
const reader = dirEntry.createReader();
const all = [];
const next = () => reader.readEntries((b) => {
if (!b.length) return resolve(all);
all.push(...b);
next();
}, reject);
next();
});
const collectFiles = async (entry, result = []) => {
if (entry.isFile) {
result.push({ path: entry.fullPath, file: await getFile(entry) });
} else if (entry.isDirectory) {
for (const child of await readDir(entry)) {
await collectFiles(child, result);
}
}
return result;
};
document.querySelector('#drop-zone').addEventListener('drop', async (event) => {
event.preventDefault();
const entries = [...event.dataTransfer.items]
.map((item) => item.webkitGetAsEntry())
.filter(Boolean);
for (const entry of entries) {
const files = await collectFiles(entry.filesystem.root);
files.forEach(({ path, file }) => console.log(path, file.size, 'Bytes'));
}
});
// Wichtig · Fallstricke
- Nicht verwechseln:
FileSystemgehört zum älteren File and Directory Entries API und hat nichts mit dem neueren File System API zu tun (FileSystemHandle,showOpenFilePicker(), Origin Private File System übernavigator.storage.getDirectory()). Für neue Anwendungen mit Schreibzugriff ist das neuere API die bessere Wahl. - Nur lesend: Dateisysteme aus Drag & Drop oder
webkitdirectorylassen sich nicht beschreiben. Das früher in Chrome verfügbare sandboxedwindow.webkitRequestFileSystem()ist veraltet und nicht standardisiert. - Synchron zugreifen:
webkitGetAsEntry()muss direkt imdrop-Handler aufgerufen werden, also vor dem erstenawait. Danach istdataTransfer.itemsleer. readEntries()liefert Teilergebnisse: Chrome gibt z. B. höchstens 100 Einträge pro Aufruf zurück. Deshalb so lange aufrufen, bis ein leeres Array kommt.- Callback-basiert: Das API nutzt Callbacks statt Promises. Für
async/awaitmuss man die Aufrufe selbst in Promises verpacken. - Kompatibilität: Wird von Chrome, Edge, Firefox und Safari unterstützt, der Zugang läuft aber teils nur über Methoden mit
webkit-Präfix. Der Wert vonnamehängt vom Browser ab, man sollte sich nicht auf ihn verlassen.