Signatur
Beschreibung
ProgressEvent.total gibt an, wie groß die Datenmenge ist, die insgesamt übertragen oder verarbeitet werden soll. Bei HTTP-Übertragungen mit XMLHttpRequest sind das Bytes. Beim Download entspricht der Wert in der Regel dem Content-Length-Header der Antwort, beim Upload der Größe des gesendeten Request-Bodys. Beim FileReader ist es die Größe der gelesenen Datei bzw. des Blob.
Zusammen mit ProgressEvent.loaded lässt sich ein Fortschritt in Prozent berechnen, etwa für Fortschrittsbalken oder Statusanzeigen. Ob total überhaupt aussagekräftig ist, zeigt die Eigenschaft ProgressEvent.lengthComputable. Ist sie false, steht in total der Wert 0. Dann ist keine Prozentangabe möglich, und Sie sollten stattdessen eine unbestimmte Fortschrittsanzeige verwenden.
Die Eigenschaft ist schreibgeschützt. Eigene ProgressEvent-Objekte können Sie aber über den Konstruktor mit einem beliebigen total-Wert erzeugen, zum Beispiel für eigene Fortschrittsmeldungen in Bibliotheken oder für Tests.
Rückgabewert
0, wenn die Größe unbekannt ist (lengthComputable === false).Beispiele
Download-Fortschritt mit XMLHttpRequest anzeigen
const xhr = new XMLHttpRequest();
xhr.open('GET', '/dateien/bericht.pdf');
xhr.responseType = 'blob';
xhr.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const prozent = Math.round((event.loaded / event.total) * 100);
console.log(`${event.loaded} von ${event.total} Bytes (${prozent} %)`);
} else {
// Gesamtgröße unbekannt, z. B. fehlender Content-Length-Header
console.log(`${event.loaded} Bytes geladen (Gesamtgröße unbekannt)`);
}
});
xhr.send();
Upload-Fortschritt in ein <progress>-Element schreiben
const input = document.querySelector('#datei');
const balken = document.querySelector('progress');
input.addEventListener('change', () => {
const formData = new FormData();
formData.append('datei', input.files[0]);
const xhr = new XMLHttpRequest();
xhr.open('POST', '/api/upload');
// Upload-Events hängen an xhr.upload, nicht an xhr selbst
xhr.upload.onprogress = (event) => {
if (event.lengthComputable) {
balken.max = event.total;
balken.value = event.loaded;
} else {
balken.removeAttribute('value'); // unbestimmter Zustand
}
};
xhr.send(formData);
});
Datei einlesen mit FileReader
const input = document.querySelector('input[type=file]');
input.addEventListener('change', () => {
const reader = new FileReader();
reader.onprogress = (event) => {
console.log(`Gelesen: ${event.loaded} / ${event.total} Bytes`);
};
reader.onload = (event) => {
console.log('Fertig, Gesamtgröße:', event.total);
};
reader.readAsArrayBuffer(input.files[0]);
});
Eigenes ProgressEvent erzeugen
const event = new ProgressEvent('progress', {
lengthComputable: true,
loaded: 30,
total: 120
});
console.log(event.total); // 120
console.log(event.loaded / event.total); // 0.25
event.total = 999; // wird ignoriert, schreibgeschützt
console.log(event.total);
// Wichtig · Fallstricke
- Immer
lengthComputableprüfen: Ist die Größe unbekannt, lieferttotalden Wert0. Die Rechnungloaded / totalergibt dannInfinitybzw.NaN. - Komprimierte Antworten: Bei
Content-Encoding: gzipoderbrbezieht sichContent-Lengthauf die komprimierten Bytes.loadedzählt aber je nach Browser die entpackten Bytes. Dadurch kannloadedgrößer werden alstotal, und die Prozentangabe steigt über 100 %. Begrenzen Sie den Wert zur Sicherheit mitMath.min(1, loaded / total). - CORS: Bei Anfragen an andere Ursprünge muss der Server
Content-Lengthsenden. Außerdem darf der Header nicht durch Chunked Transfer Encoding fehlen. Fehlt die Angabe, istlengthComputablegleichfalse. Upload-Events aufxhr.uploadlösen bei Cross-Origin-Anfragen einen Preflight aus. - Fetch-API:
fetch()löst keineProgressEvents aus. Dort lesen Sieresponse.headers.get('Content-Length')und zählen die Bytes selbst überresponse.body.getReader(). - Laut Spezifikation ist der Typ
unsigned long long. Für Werte über 253 Bytes gibt es in der Praxis also kaum Genauigkeitsprobleme. - Die Eigenschaft wird in allen modernen Browsern unterstützt, außerdem in Web Workern.