is it possible to show the user via javascript how much is left (in kb) to fully download a gif file from a remote server?
function downgif(id, img){
//show downloading
Show('downloadgif');
//chenge img
document.getElementById(id).src=img;
//test if complete
var completeInterval = null, renderedInterval = null, count = 0;
var theImg = document.getElementById(id);
theImg.src = img;
// Wait for image to be loaded (but not necessarily rendered)
completeInterval = setInterval(function() {
if (theImg.complete) {
// Cancel checking once IMG is loaded OR we've tried for ~9s already
clearInterval(completeInterval);
completeInterval = null;
// IMG is now 'complete' - but that just means it's in the render queue...
// Wait for naturalWidth and naturalHeight to be > 0 since this shows
// that the image is done being RENDERED (not just 'loaded/complete')
renderedInterval = setInterval(function() {
if (theImg.naturalHeight > 0 && theImg.naturalWidth > 0) {
clearInterval(renderedInterval);
renderedInterval = null;
//hide downliading
Hide('downloadgif');
}
}, 100);
}
}, 450);
}
Yes, it’s possible to display how much is left to fully download a GIF file from a remote server, but it requires using the XMLHttpRequest or Fetch API to track download progress (rather than a <img />
)
XMLHttpRequest
XMLHttpRequest provides a onprogress
event which can be used to calculate the progress of a download.
function downgif(url, imgElementId) {
const xhr = new XMLHttpRequest();
const imgElement = document.getElementById(imgElementId);
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onprogress = function(event) {
const kbRemaining = ((event.total - event.loaded) / 1024).toFixed(2);
console.log(`Remaining: ${kbRemaining} KB`);
};
xhr.onload = function() {
const blobUrl = URL.createObjectURL(xhr.response);
imgElement.src = blobUrl;
console.log("Download complete.");
};
xhr.send();
}
const url = "https://upload.wikimedia.org/wikipedia/commons/3/31/-WikiForHumanRights2022Right_to_a_healthy_environment._%281%29_%281%29.gif";
downgif(url, 'gifDisplay');
<img id="gifDisplay">
Fetch
fetch
allows you to download the response as a stream, which can also have it’s progress calculated from the Content-Length
header.
async function downgif(url, imgElementId) {
const imgElement = document.getElementById(imgElementId);
const response = await fetch(url);
const contentLength = response.headers.get('Content-Length');
const total = parseInt(contentLength, 10);
let loaded = 0;
const reader = response.body.getReader();
const chunks = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
loaded += value.length;
const kbRemaining = ((total - loaded) / 1024).toFixed(2);
console.log(`Remaining: ${kbRemaining} KB`);
}
const blob = new Blob(chunks);
const blobUrl = URL.createObjectURL(blob);
imgElement.src = blobUrl;
console.log("Download complete.");
}
const url = "https://upload.wikimedia.org/wikipedia/commons/3/31/-WikiForHumanRights2022Right_to_a_healthy_environment._%281%29_%281%29.gif";
downgif(url, 'gifDisplay');
<img id="gifDisplay">
If you want to test this on other large GIFs, Wikipedia provides many examples (which is where the demo GIF I used came from)
2