AnthumChris collected some JavaScript scripts to track the progress of fetch
requests that download files/data. It works by leveraging the ReadableStream interface from the Streams API.
A “simple” example is this:
fetch('https://fetch-progress.anthum.com/30kbps/images/sunrise-baseline.jpg')
.then(response => {
if (!response.ok) {
throw Error(response.status+' '+response.statusText)
}
if (!response.body) {
throw Error('ReadableStream not yet supported in this browser.')
}
// to access headers, server must send CORS header "Access-Control-Expose-Headers: content-encoding, content-length x-file-size"
// server must send custom x-file-size header if gzip or other content-encoding is used
const contentEncoding = response.headers.get('content-encoding');
const contentLength = response.headers.get(contentEncoding ? 'x-file-size' : 'content-length');
if (contentLength === null) {
throw Error('Response size header unavailable');
}
const total = parseInt(contentLength, 10);
let loaded = 0;
return new Response(
new ReadableStream({
start(controller) {
const reader = response.body.getReader();
read();
function read() {
reader.read().then(({done, value}) => {
if (done) {
controller.close();
return;
}
loaded += value.byteLength;
console.log(Math.round(loaded/total*100)+'%');
controller.enqueue(value);
read();
}).catch(error => {
console.error(error);
controller.error(error)
})
}
}
})
);
})
.then(response => response.blob())
.then(data => {
console.log('download completed');
// document.getElementById('img').src = URL.createObjectURL(data);
})
.catch(error => {
console.error(error);
});
If that code confuses you, it’s mostly the Fetch + ReadableStream
example code from MDN. The key additions are:
- Extract the length from the
content-length
header. If some encoding is used, the server must send thex-file-size
header instead - Store
total
bytes andloaded
- Increment
loaded
and calculate the progress (here: logged to the console) - Do something with the data (here: commented out)
Can also be used from within a ServiceWorker.
Fetch & Streams API Progress Indicator Source Code (GitHub) →
Fetch & Streams API Progress Indicator Demos →