Start · Sprachen · JavaScript · Referenz · FileSystemFileEntry.file()

FileSystemFileEntry.file()

Methode

Liefert asynchron über einen Callback ein <code>File</code>-Objekt, mit dem sich der Inhalt der durch den Eintrag dargestellten Datei lesen lässt.

seit JavaScript Baseline: alle modernen Browser (File and Director Kategorie: webapi

Signatur

FileSystemFileEntry.prototype.file(successCallback, errorCallback)

Beschreibung

Die Methode file() des Interfaces FileSystemFileEntry wandelt einen Dateieintrag in ein echtes File-Objekt um. Dieses File erbt von Blob. Seinen Inhalt kannst du daher mit text(), arrayBuffer(), stream() oder einem FileReader lesen oder ihn per FormData hochladen.

Solche Einträge bekommst du vor allem an zwei Stellen: beim Drag & Drop über DataTransferItem.webkitGetAsEntry() und bei <input type="file" webkitdirectory> bzw. über HTMLInputElement.webkitEntries. Ein typischer Fall ist das rekursive Durchlaufen eines Ordners, den jemand in den Browser gezogen hat. Dafür braucht man FileSystemDirectoryEntry, createReader() und am Ende file() für jede einzelne Datei.

Die API arbeitet mit Callbacks und nicht mit Promises. In modernem Code packt man file() deshalb meist in ein Promise, damit man async/await verwenden kann. Die Methode gibt selbst undefined zurück. Das Ergebnis kommt ausschließlich über successCallback an.

Parameter

Name Typ Default Beschreibung
$successCallback Pflicht (file: File) => void Wird aufgerufen, sobald das File-Objekt bereitsteht. Die Funktion erhält die Datei als einziges Argument.
$errorCallback (error: DOMException) => void Wird bei einem Fehler aufgerufen, z. B. wenn die Datei inzwischen fehlt (NotFoundError) oder der Zugriff nicht erlaubt ist (SecurityError).

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Das File-Objekt kommt asynchron über successCallback.

Beispiele

Eine per Drag & Drop abgelegte Datei lesen

const dropZone = document.querySelector('#drop');

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.file(
        async (file) => {
          console.log(file.name, file.size, 'Bytes');
          console.log(await file.text());
        },
        (err) => console.error('Lesefehler:', err.name)
      );
    }
  }
});
notizen.txt 42 Bytes Hallo Welt ...

file() als Promise für async/await

const getFile = (fileEntry) =>
  new Promise((resolve, reject) => fileEntry.file(resolve, reject));

// Nutzung, z. B. innerhalb eines drop-Handlers:
const readEntry = async (entry) => {
  const file = await getFile(entry);
  const buffer = await file.arrayBuffer();
  console.log(`${file.name}: ${buffer.byteLength} Bytes, Typ ${file.type || 'unbekannt'}`);
};
bild.png: 20480 Bytes, Typ image/png

Ordner rekursiv durchlaufen und alle Dateien sammeln

const getFile = (entry) => new Promise((res, rej) => entry.file(res, rej));

const readAllEntries = (dirEntry) => new Promise((resolve, reject) => {
  const reader = dirEntry.createReader();
  const all = [];
  const next = () => reader.readEntries((batch) => {
    if (batch.length === 0) return resolve(all);
    all.push(...batch);
    next(); // readEntries liefert Einträge in Paketen
  }, reject);
  next();
});

const collectFiles = async (entry) => {
  if (entry.isFile) return [await getFile(entry)];
  const children = await readAllEntries(entry);
  const nested = await Promise.all(children.map(collectFiles));
  return nested.flat();
};

document.querySelector('#drop').addEventListener('drop', async (e) => {
  e.preventDefault();
  // Einträge synchron holen, bevor der erste await läuft!
  const entries = [...e.dataTransfer.items]
    .map((item) => item.webkitGetAsEntry())
    .filter(Boolean);
  const files = (await Promise.all(entries.map(collectFiles))).flat();
  console.log(files.map((f) => f.name));
});
["index.html", "style.css", "app.js"]

// Wichtig · Fallstricke

  • Nur Callbacks: file() gibt kein Promise zurück. await entry.file() ergibt undefined. Du musst die Methode also selbst in ein Promise packen.
  • Kurzlebige DataTransfer-Daten: Rufe webkitGetAsEntry() synchron im drop-Handler auf. Nach dem ersten await ist dataTransfer.items leer. Die Einträge selbst bleiben aber gültig.
  • readEntries in Paketen: Chrome liefert höchstens 100 Einträge pro Aufruf. Rufe readEntries() deshalb so lange auf, bis ein leeres Array zurückkommt.
  • Prüfe isFile: file() gibt es nur bei FileSystemFileEntry. Verzeichniseinträge (FileSystemDirectoryEntry) haben diese Methode nicht.
  • Kompatibilität: Chrome, Edge, Firefox und Safari unterstützen die Methode. Die Einstiegsfunktionen tragen jedoch weiterhin das Präfix webkit. Für neue Projekte mit Lese- und Schreibzugriff ist die File System Access API (FileSystemFileHandle.getFile()) die moderne Alternative, sie wird aber nicht überall unterstützt.
  • Sicherheit: Dateiname und MIME-Typ (file.type) kommen vom Nutzer bzw. Betriebssystem und sind nicht vertrauenswürdig. Gib Inhalte nie ungeprüft per innerHTML aus.