Signatur
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 einFile-Objekt zurück odernull, wenn das Element keine Datei ist.webkitGetAsEntry(): gibt einenFileSystemEntryzurück; damit lassen sich auch abgelegte Ordner rekursiv auslesen.getAsFileSystemHandle(): gibt ein Promise auf einFileSystemFileHandle/FileSystemDirectoryHandlezurü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
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));
}
}
});
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);
});
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);
});
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));
});
// Wichtig · Fallstricke
- Nur synchron gültig: Die
DataTransferItemListund ihre Elemente sind nur während des Event-Handlers nutzbar (Lese-/Schutzmodus). Nach einemawaitoder in einemsetTimeoutist die Liste leer undgetAsFile()gibtnullzurück. Sammeln Sie daherFile-Objekte bzw. Einträge sofort ein. - Geschützter Modus in
dragstart/dragover: Währenddragenter/dragoversind nurkindundtypelesbar, 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).typekann 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/htmlniemals ungefiltert perinnerHTMLeinfü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.prototypeprüfen.readEntries()liefert in Chromium höchstens 100 Einträge pro Aufruf – so lange wiederholen, bis ein leeres Array kommt.