Signatur
Beschreibung
Die schreibgeschützte Eigenschaft upload gibt ein XMLHttpRequestUpload-Objekt zurück. Es gehört fest zu der jeweiligen XMLHttpRequest-Instanz und ist ein EventTarget, an dem sich Listener für den Upload-Teil einer Anfrage registrieren lassen, also für das Senden des Request-Bodys an den Server.
Folgende Events stehen zur Verfügung (jeweils per addEventListener() oder als on…-Eigenschaft):
loadstart: Der Upload beginnt.progress: Wird regelmäßig ausgelöst. DasProgressEvententhältloaded,totalundlengthComputable.load: Der Upload ist erfolgreich abgeschlossen. Die Server-Antwort ist dann aber noch nicht zwingend angekommen.error,abort,timeout: Der Upload ist fehlgeschlagen, wurde abgebrochen oder hat das Zeitlimit überschritten.loadend: Der Upload ist beendet, egal ob erfolgreich oder nicht.
Typische Einsatzfälle sind Fortschrittsbalken beim Hochladen von Dateien mit FormData oder Blob. Wichtig: Die fetch()-API bietet bis heute keine gleichwertige, breit unterstützte Möglichkeit, den Upload-Fortschritt zu beobachten. Deshalb ist xhr.upload dafür weiterhin das Mittel der Wahl.
Rückgabewert
XMLHttpRequestUpload-Objekt (ein EventTarget). Bei jedem Zugriff kommt dieselbe Instanz zurück.Beispiele
Datei-Upload mit Fortschrittsanzeige
const input = document.querySelector('#datei');
const balken = document.querySelector('progress');
input.addEventListener('change', () => {
const datei = input.files[0];
if (!datei) return;
const formData = new FormData();
formData.append('datei', datei);
const xhr = new XMLHttpRequest();
// Listener VOR send() registrieren
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const prozent = Math.round((event.loaded / event.total) * 100);
balken.value = prozent;
console.log(`Hochgeladen: ${prozent} %`);
}
});
xhr.upload.addEventListener('load', () => console.log('Upload abgeschlossen'));
xhr.addEventListener('load', () => console.log('Server-Antwort:', xhr.status));
xhr.open('POST', '/api/upload');
xhr.send(formData);
});
Upload als Promise mit Fortschritts-Callback und Abbruch
const uploadMitFortschritt = (url, body, onProgress, signal) =>
new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.upload.onprogress = (e) => {
if (e.lengthComputable) onProgress(e.loaded / e.total);
};
xhr.upload.onerror = () => reject(new Error('Netzwerkfehler beim Upload'));
xhr.upload.onabort = () => reject(new DOMException('Abgebrochen', 'AbortError'));
xhr.onload = () =>
xhr.status >= 200 && xhr.status < 300
? resolve(xhr.response)
: reject(new Error(`HTTP ${xhr.status}`));
signal?.addEventListener('abort', () => xhr.abort());
xhr.open('POST', url);
xhr.responseType = 'json';
xhr.send(body);
});
// Nutzung
const controller = new AbortController();
const blob = new Blob([new Uint8Array(5_000_000)]);
try {
const antwort = await uploadMitFortschritt(
'/api/upload',
blob,
(anteil) => console.log(`${(anteil * 100).toFixed(0)} %`),
controller.signal
);
console.log('Fertig:', antwort);
} catch (err) {
console.error(err.message);
}
Alle Upload-Phasen protokollieren
const xhr = new XMLHttpRequest();
const phasen = ['loadstart', 'progress', 'load', 'error', 'abort', 'timeout', 'loadend'];
for (const typ of phasen) {
xhr.upload.addEventListener(typ, (e) => {
console.log(`upload:${e.type}`, e.loaded, '/', e.total);
});
}
xhr.open('POST', '/api/echo');
xhr.send('Hallo Server!');
// Wichtig · Fallstricke
- Listener vor
send()registrieren: Listener, die erst nachsend()hinzukommen, verpassen unter Umständen Events oder werden gar nicht ausgelöst. - CORS-Preflight: Schon ein einziger Listener auf
xhr.uploadmacht einen Cross-Origin-Request zu einer „nicht einfachen“ Anfrage. Der Browser schickt dann einenOPTIONS-Preflight, und der Server muss darauf korrekt antworten, sonst schlägt die Anfrage fehl. - Ohne Body keine Upload-Events: Bei
GET/HEADodersend()ohne Body werden keine Upload-Events ausgelöst. event.lengthComputableimmer prüfen. Ist der Wertfalse, kanntotalgleich0sein.xhr.upload.onloadbedeutet nur, dass die Daten gesendet wurden. Ob der Server sie angenommen hat, zeigt erstxhr.onloadzusammen mitxhr.status.- Die Fortschrittswerte spiegeln den Stand der Netzwerkpuffer des Browsers wider und sind deshalb nicht exakt. Bei kleinen Uploads kommt oft nur ein einziges
progress-Event. - In Service Workern gibt es
XMLHttpRequestnicht.fetch()unterstützt Upload-Fortschritt bisher nicht breit; Streaming-Request-Bodys gibt es nur in Chromium und nur mit HTTP/2+. - Die Eigenschaft ist in allen modernen Browsern verfügbar, ab IE 10.