Start · Sprachen · JavaScript · Referenz · FileSystemDirectoryEntry

FileSystemDirectoryEntry

Schnittstelle

Stellt in der File and Directory Entries API ein Verzeichnis dar. Man kann damit Unterverzeichnisse und Dateien abrufen und den Inhalt über <code>createReader()</code> auflisten.

seit JavaScript Baseline: alle modernen Browser (Chrome, Edge, Fir Kategorie: webapi

Signatur

interface FileSystemDirectoryEntry extends FileSystemEntry

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 einen FileSystemDirectoryReader zurück, mit dem man die Einträge des Verzeichnisses auflistet.
  • getFile(path, options, successCallback, errorCallback): holt einen FileSystemFileEntry über einen relativen oder absoluten Pfad.
  • getDirectory(path, options, successCallback, errorCallback): holt einen untergeordneten FileSystemDirectoryEntry.

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

Typ
FileSystemDirectoryReader | void
Beschreibung
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}`);
    }
  }
});
Ordner: fotos (/fotos)

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);
[{ path: '/fotos/urlaub/strand.jpg', size: 204811 }, ...]

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);
// }
Projekt: mein-projekt

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);
true /projekt/src

// 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 im drop-Event aufrufen. Nach einem await ist die DataTransferItemList leer. Deshalb zuerst alle Einträge einsammeln und danach asynchron verarbeiten.
  • Nur Callbacks: Die API kennt keine Promises. Wenn man den errorCallback weglässt, gehen Fehler wie NotFoundError unbemerkt verloren.
  • Kompatibilität: Wird von allen modernen Browsern unterstützt. Die Einstiegspunkte tragen aber historisch das Präfix webkit (webkitGetAsEntry, webkitEntries). Die veralteten Methoden removeRecursively() und das ältere DirectoryEntry aus 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 innerHTML ausgegeben werden (XSS-Gefahr).