I create an Iframe on the fly and set as the url a page that downloads a binary file (xls, doc…). While files are downloading I show an animation. When does not, I hide it.
The problem is that Chrome does not know when the files are fully downloaded, that is when the iframe is completely loaded. I use the iframe property readyState to check the iframe state:
var iframe = document.createElement("iframe");
iframe.style.visibility = "hidden";
// I start a progress animation
window.setTimeout(showProgressAnimation, 1000);
// I start the file download
iframe.src ='GetFile.aspx?file=' + fileName;
document.body.appendChild(iframe);
function showProgressAnimation() {
if (iframe.readyState == "complete" || iframe.readyState == "interactive") {
// I stop the animation and show the page
animation.style.display = 'none';
progressBar.hide();
$('#page').show();
}
else {
// Chrome is always getting into this line
window.setTimeout(showProgressAnimation, 1000);
}
}
So the result is an infinite loop.
I’ve tried the following and it works in Firefox and Chrome but not when the contents are a binary file:
if ($.browser.mozilla || $.browser.webkit ) {
iframe.onload = function showProgressAnimation() {
animation.style.display = 'none';
progressBar.hide();
$('#page').show();
}
}
// IE
else{
window.setTimeout(showProgressAnimation, 1000);
}
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
You can use the onload to signaling the load of the iframe
here is a simple example that working
var iframe = document.createElement("iframe");
iframe.style.display = "none";
// this function will called when the iframe loaded
iframe.onload = function (){
iframe.style.display = "block";
alert("loaded");
};
// set the src last.
iframe.src ='http://www.test.com';
// add it to the page.
document.getElementById("one").appendChild(iframe);
Tested here:
http://jsfiddle.net/48MQW/5/
With src loaded last.
http://jsfiddle.net/48MQW/24/
Method 2
The downloadable file content doesn’t trigger the readystatechange event handler or the onload event handler. This couse you can set a cookie in server side together the file content, and client side check this cookie periodically. For example:
server
response.cookie('fileDownloaded','true');
response.header('attachment','your-file-name.any');
//...write bytes to response...
client
var checker = setInterval(()=>{
if(document.cookie.indexOf('fileDownloaded')>-1){
alert('done');
clearInterval(checker);
}
},100);
Of course, you can use your framework to check the cookie value correctly, this is just a poc, not a safe cookie parser.
Method 3
Please try this – you are really mixing dom and jQuery from line to line
var tId;
function stopAnim() {
// I stop the animation and show the page
animation.hide();
progressBar.hide();
$('#page').show();
clearInterval(tId);
}
var iframe = $("<iframe />");
iframe.css("visibility","hidden");
iframe.on("readystatechange",function() {
if (this.readyState == "complete" || this.readyState == "interactive") {
stopAnim();
}
});
iframe.on("load",function() { // can possibly be deleted
if (tId) {
stopAnim();
}
});
iframe.attr("src","GetFile.aspx?file=" + fileName);
$("body").append(iframe);
tId = setInterval(function() {
// update progress here
}, 1000); //
Method 4
Sarkiroka’s solution worked for me. I have added an instance id to the cookie name to provide a thread safe solution:
const instanceId = "some uuid retrieved from client";
response.cookie(`fileDownloaded-${instanceId}`,'true', { path: '/', secure: true, maxAge: 90000});
response.header('attachment','your-file-name.any');
//...write bytes to response...
client
var checker = setInterval(()=>{
if(document.cookie.indexOf(`fileDownloaded-${instanceId}`)>-1){
alert('done');
clearInterval(checker);
}
},100);
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0