PROWAREtech

articles » current » javascript » download-images-with-progress-indicator

JavaScript: Download Images with Progress Indicator Bar

How to download images to the browser while showing the user a percent completion of the download while they wait.

This prototype function Image.progressload() will download an image and issue calls to a progress callback function while the download is happening. See code notes for more information.

This code is compatible with Internet Explorer 11 (IE11) if still developing for this browser.


// NOTE: progress_callback is called with the percent of download completion passed,
// and done_callback is called when the download is complete with the image object passed
Image.prototype.progressload = function (image_url, progress_callback, done_callback) {
	var this_img = this, xhr = new XMLHttpRequest();

	xhr.open("get", image_url, true);
	xhr.responseType = "arraybuffer";

	xhr.onload = function () {

		var blob = new Blob([this.response]);
		this_img.src = URL.createObjectURL(blob);

		if (typeof done_callback == "function") {
			done_callback(this_img);
		}
		setTimeout(function () { URL.revokeObjectURL(this_img.src); }, 5000); // NOTE: this frees the resource after it has presumably been used
	};

	xhr.onprogress = function (ev) {
		if (ev.lengthComputable && typeof progress_callback == "function") {
			progress_callback((ev.loaded / ev.total) * 100);
		}
	};

	xhr.onloadstart = function () {
		if (typeof progress_callback == "function") {
			progress_callback(0);
		}
	};

	xhr.onloadend = function () {
		if (typeof progress_callback == "function") {
			progress_callback(100);
		}
	}

	xhr.send();
};

Here is an alternate version that, under heavy load and usage is not as reliable due to a bug in Chrome/Edge, but it should work best, certainly if and when the bug is fixed. This is the best code!


// NOTE: progress_callback is called with the percent of download completion passed,
// and done_callback is called when the download is complete with the image object passed
Image.prototype.progressload = function (image_url, progress_callback, done_callback) {
	var this_img = this, xhr = new XMLHttpRequest();

	if (typeof done_callback == "function") {
		this_img.onload = function () {
			done_callback(this_img);
		};
	}

	xhr.open("get", image_url, true);
	xhr.responseType = "arraybuffer";

	xhr.onload = function () {

		var blob = new Blob([this.response]);
		this_img.src = URL.createObjectURL(blob);
		setTimeout(function () { URL.revokeObjectURL(this_img.src); }, 5000); // NOTE: this frees the resource after it has presumably been used
	};

	xhr.onprogress = function (ev) {
		if (ev.lengthComputable && typeof progress_callback == "function") {
			progress_callback((ev.loaded / ev.total) * 100);
		}
	};

	xhr.onloadstart = function () {
		if (typeof progress_callback == "function") {
			progress_callback(0);
		}
	};

	xhr.onloadend = function () {
		if (typeof progress_callback == "function") {
			progress_callback(100);
		}
	}

	xhr.send();
};

An example HTML page using the above prototype. It has a very much not elegant red progress bar that shows the progress of the download and then displays the image when it is done with its download. NOTE: this only works well on large images.


<!DOCTYPE html>
<html lang="en-us">
<head>
	<meta charset="utf-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
	<title>Download Images with Progress Using JavaScript</title>
	<style>
		body {
			margin: 0;
			padding: 0;
		}
		img {
			width: 100%;
			height: auto;
		}
	</style>
</head>
<body>
	<div class="page">
<script type="text/javascript">
// NOTE: progress_callback is called with the percent of download completion passed,
// and done_callback is called when the download is complete with the image object passed
Image.prototype.progressload = function (image_url, progress_callback, done_callback) {
	var this_img = this, xhr= new XMLHttpRequest();

	xhr.open("get", image_url, true);
	xhr.responseType = "arraybuffer";

	xhr.onload = function () {

		var blob = new Blob([this.response]);
		this_img.src = URL.createObjectURL(blob);

		if (typeof done_callback == "function") {
			done_callback(this_img);
		}
		setTimeout(function () { URL.revokeObjectURL(this_img.src); }, 5000); // NOTE: this frees the resource after it has presumably been used
	};

	xhr.onprogress = function (ev) {
		if (ev.lengthComputable && typeof progress_callback == "function") {
			progress_callback((ev.loaded / ev.total) * 100);
		}
	};

	xhr.onloadstart = function () {
		if (typeof progress_callback == "function") {
			progress_callback(0);
		}
	};

	xhr.onloadend = function () {
		if (typeof progress_callback == "function") {
			progress_callback(100);
		}
	}

	xhr.send();
};

window.onload = function () {
	var img = new Image();
	img.progressload("/img/blob.jpg?v=" + Number(new Date()), function (percent) { // NOTE: specify a parameter to force a new download
		var prog = document.getElementById("progress");
		prog.style.width = percent + "%";
		prog.innerText = Math.round(percent) + "%";
	}, function (image) {
		document.body.appendChild(image);
	});
};
</script>
<div style="background-color:transparent;height:25px;width:100%;text-align:left;">
	<div id="progress" style="display:inline-block;background-color:red;color:white;height:inherit;width:0;overflow:hidden;line-height:25px;"></div>
</div>

</body>
</html>

PROWAREtech

Hello there! How can I help you today?
Ask any question

PROWAREtech

This site uses cookies. Cookies are simple text files stored on the user's computer. They are used for adding features and security to this site. Read the privacy policy.
ACCEPT REJECT