Start · Sprachen · JavaScript · Referenz · DataTransferItem

DataTransferItem

Schnittstelle

Ein <code>DataTransferItem</code> steht für ein einzelnes Datenelement (Text oder Datei) bei Drag-and-Drop- oder Zwischenablage-Vorgängen.

seit JavaScript Baseline: alle modernen Browser (webkitGetAsEntry( Kategorie: webapi

Signatur

interface DataTransferItem

Beschreibung

Ein DataTransferItem ist genau ein Eintrag in einer DataTransferItemList. Diese Liste erreichen Sie über event.dataTransfer.items (bei Drag-Events wie drop) oder über event.clipboardData.items (bei paste). Jedes Element ist entweder eine Zeichenkette (z. B. text/plain, text/html, text/uri-list) oder eine Datei.

Wichtige Mitglieder:

  • kind (nur lesbar): "string" oder "file".
  • type (nur lesbar): MIME-Typ des Elements, z. B. "image/png". Kann bei unbekannten Dateien leer sein.
  • getAsString(callback): übergibt den Textinhalt asynchron an einen Callback (kein Promise!).
  • getAsFile(): gibt ein File-Objekt zurück oder null, wenn das Element keine Datei ist.
  • webkitGetAsEntry(): gibt einen FileSystemEntry zurück; damit lassen sich auch abgelegte Ordner rekursiv auslesen.
  • getAsFileSystemHandle(): gibt ein Promise auf ein FileSystemFileHandle/FileSystemDirectoryHandle zurück (File System Access API, nur Chromium).

Sie verwenden DataTransferItem, wenn Sie beim Ablegen oder Einfügen gezielt nach Art und Typ filtern wollen – etwa nur Bilder aus der Zwischenablage übernehmen oder Ordnerstrukturen per Drag-and-Drop hochladen. Für einfache Fälle genügen oft dataTransfer.files bzw. dataTransfer.getData().

Parameter

Name Typ Default Beschreibung
$callback Pflicht (data: string) => void Nur für getAsString(): Funktion, die asynchron mit dem Textinhalt aufgerufen wird. Wird bei kind === "file" nie aufgerufen.

Rückgabewert

Typ
DataTransferItem
Beschreibung
Instanzen werden nicht selbst erzeugt, sondern stammen aus DataTransferItemList (z. B. event.dataTransfer.items[0]) oder werden über items.add() angelegt. getAsFile() liefert File | null, getAsString() liefert undefined, webkitGetAsEntry() liefert FileSystemEntry | null.

Beispiele

Abgelegte Elemente nach Art unterscheiden

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

// dragover muss abgebrochen werden, sonst feuert drop nicht
dropZone.addEventListener('dragover', (e) => e.preventDefault());

dropZone.addEventListener('drop', (e) => {
  e.preventDefault();
  for (const item of e.dataTransfer.items) {
    if (item.kind === 'file') {
      const file = item.getAsFile();
      console.log(`Datei: ${file.name} (${file.type}, ${file.size} Bytes)`);
    } else if (item.kind === 'string' && item.type === 'text/plain') {
      item.getAsString((text) => console.log('Text:', text));
    }
  }
});
Datei: foto.png (image/png, 48213 Bytes)

Bild aus der Zwischenablage einfügen

document.addEventListener('paste', (e) => {
  const imageItem = [...e.clipboardData.items]
    .find((item) => item.kind === 'file' && item.type.startsWith('image/'));
  if (!imageItem) return;

  e.preventDefault();
  const file = imageItem.getAsFile();
  const img = document.createElement('img');
  img.src = URL.createObjectURL(file);
  img.onload = () => URL.revokeObjectURL(img.src);
  document.body.append(img);
  console.log('Eingefügt:', file.type);
});
Eingefügt: image/png

getAsString() in ein Promise verpacken

const getString = (item) => new Promise((resolve) => item.getAsString(resolve));

const target = document.querySelector('#editor');
target.addEventListener('dragover', (e) => e.preventDefault());
target.addEventListener('drop', async (e) => {
  e.preventDefault();
  // Items SYNCHRON einsammeln – nach dem ersten await ist die Liste leer
  const items = [...e.dataTransfer.items].filter((i) => i.kind === 'string');
  const results = await Promise.all(
    items.map(async (i) => ({ type: i.type, data: await getString(i) }))
  );
  console.table(results);
});
┌─────────┬────────────────┬──────────────────────────┐ │ (index) │ type │ data │ │ 0 │ 'text/plain' │ 'https://example.com' │ │ 1 │ 'text/uri-list'│ 'https://example.com' │ └─────────┴────────────────┴──────────────────────────┘

Abgelegten Ordner rekursiv auslesen

const readEntry = async (entry, path = '') => {
  if (entry.isFile) {
    const file = await new Promise((res, rej) => entry.file(res, rej));
    console.log(path + file.name);
  } else if (entry.isDirectory) {
    const reader = entry.createReader();
    let batch;
    // readEntries liefert Ergebnisse stückweise – so lange lesen, bis leer
    do {
      batch = await new Promise((res, rej) => reader.readEntries(res, rej));
      for (const child of batch) await readEntry(child, `${path}${entry.name}/`);
    } while (batch.length > 0);
  }
};

const zone = document.querySelector('#drop-zone');
zone.addEventListener('dragover', (e) => e.preventDefault());
zone.addEventListener('drop', (e) => {
  e.preventDefault();
  const entries = [...e.dataTransfer.items]
    .map((item) => item.webkitGetAsEntry())
    .filter(Boolean);
  entries.forEach((entry) => readEntry(entry));
});
projekt/index.html projekt/css/style.css

// Wichtig · Fallstricke

  • Nur synchron gültig: Die DataTransferItemList und ihre Elemente sind nur während des Event-Handlers nutzbar (Lese-/Schutzmodus). Nach einem await oder in einem setTimeout ist die Liste leer und getAsFile() gibt null zurück. Sammeln Sie daher File-Objekte bzw. Einträge sofort ein.
  • Geschützter Modus in dragstart/dragover: Während dragenter/dragover sind nur kind und type lesbar, nicht der Inhalt. Das ist Absicht: Webseiten sollen Daten nicht „mitlesen“, die nur darübergezogen werden.
  • getAsString() arbeitet mit einem Callback, nicht mit einem Promise – bei Bedarf selbst verpacken (siehe Beispiel).
  • type kann bei Dateien leer sein (unbekannte Endung) – verlassen Sie sich für Sicherheitsprüfungen nicht darauf, sondern validieren Sie den Inhalt serverseitig.
  • Sicherheit: Eingefügtes bzw. abgelegtes text/html niemals ungefiltert per innerHTML einfügen (XSS-Gefahr) – vorher bereinigen, z. B. mit DOMPurify oder der Sanitizer-API.
  • webkitGetAsEntry() trägt trotz Präfix in allen großen Browsern; getAsFileSystemHandle() gibt es nur in Chromium-Browsern – vor Nutzung mit 'getAsFileSystemHandle' in DataTransferItem.prototype prüfen.
  • readEntries() liefert in Chromium höchstens 100 Einträge pro Aufruf – so lange wiederholen, bis ein leeres Array kommt.