Last active
February 18, 2019 22:28
-
-
Save bspavel/44f60eab99dc12f725cb1e2084e199f1 to your computer and use it in GitHub Desktop.
[JAVASCRIPT] Show a progress bar for downloading file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
https://stackoverflow.com/questions/39589917/show-a-progress-bar-for-downloading-files-using-xhr2-ajax | |
If you want to show the user a progress-bar of the downloading process - you must do the download within the xmlhttprequest. | |
One of the problems here is that if your files are big - they will be saved in the memory of the browser before the browser | |
will write them to the disk | |
(when using the regular download files are being saved directly to the disk, which saves a lot of memory on big files). | |
Another important thing to note - in order for the lengthComputable to be true - your server must send the Content-Length | |
header with the size of the file. | |
Here is the javascript code: | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> | |
<div id="a1" data-filename="filename.xml">Click to download</div> | |
<script> | |
$('#a1').click(function() { | |
var that = this; | |
var page_url = 'download.php'; | |
var req = new XMLHttpRequest(); | |
req.open("POST", page_url, true); | |
req.addEventListener("progress", function (evt) { | |
if(evt.lengthComputable) { | |
var percentComplete = evt.loaded / evt.total; | |
console.log(percentComplete); | |
} | |
}, false); | |
req.responseType = "blob"; | |
req.onreadystatechange = function () { | |
if (req.readyState === 4 && req.status === 200) { | |
var filename = $(that).data('filename'); | |
if (typeof window.chrome !== 'undefined') { | |
// Chrome version | |
var link = document.createElement('a'); | |
link.href = window.URL.createObjectURL(req.response); | |
link.download = filename; | |
link.click(); | |
} else if (typeof window.navigator.msSaveBlob !== 'undefined') { | |
// IE version | |
var blob = new Blob([req.response], { type: 'application/force-download' }); | |
window.navigator.msSaveBlob(blob, filename); | |
} else { | |
// Firefox version | |
var file = new File([req.response], filename, { type: 'application/force-download' }); | |
window.open(URL.createObjectURL(file)); | |
} | |
} | |
}; | |
req.send(); | |
}); | |
</script> | |
And here is an example for the php code you can use: | |
<?php | |
$filename = "some-big-file"; | |
$filesize = filesize($filename); | |
header("Content-Transfer-Encoding: Binary"); | |
header("Content-Length:". $filesize); | |
header("Content-Disposition: attachment"); | |
$handle = fopen($filename, "rb"); | |
if (FALSE === $handle) { | |
exit("Failed to open stream to URL"); | |
} | |
while (!feof($handle)) { | |
echo fread($handle, 1024*1024*10); | |
sleep(3); | |
} | |
fclose($handle); | |
?> | |
Note that I added a sleep to simulate a slow connection for testing on localhost. | |
You should remove this on production :) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment