关于javascript:Iframe.readyState在Chrome中不起作用

Iframe.readyState does not work in chrome

我即时创建了一个Iframe,并将下载二进制文件(xls,doc ...)的页面设置为url。 下载文件时,我会显示动画。 如果没有,我将其隐藏。

问题是Chrome不知道何时完全下载文件,即不完全加载iframe的时间。 我使用iframe属性readyState来检查iframe状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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);
   }
}

因此结果是无限循环。

我已经尝试了以下方法,但它在Firefox和Chrome中有效,但当内容为二进制文件时则无效:

1
2
3
4
5
6
7
8
9
10
11
if ($.browser.mozilla || $.browser.webkit ) {
    iframe.onload = function showProgressAnimation() {
        animation.style.display = 'none';
        progressBar.hide();
        $('#page').show();
    }
}
// IE
else{
     window.setTimeout(showProgressAnimation, 1000);
}


您可以使用onload来表示iframe的负载

这是一个简单的例子

1
2
3
4
5
6
7
8
9
10
11
12
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);

在这里测试:
http://jsfiddle.net/48MQW/5/
最后加载src
http://jsfiddle.net/48MQW/24/


可下载文件的内容不会触发readystatechange事件处理程序或onload事件处理程序。 因此,您可以在服务器端一起设置cookie的文件内容,并由客户端定期检查此cookie。 例如:

服务器

1
2
3
response.cookie('fileDownloaded','true');
response.header('attachment','your-file-name.any');
//...write bytes to response...

客户

1
2
3
4
5
6
var checker = setInterval(()=>{
    if(document.cookie.indexOf('fileDownloaded')>-1){
        alert('done');
        clearInterval(checker);
    }
},100);

当然,您可以使用您的框架来正确检查cookie值,这只是poc,而不是安全的cookie解析器。


请尝试一下-您真的在一行到一行地混合dom和jQuery

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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); //


Sarkiroka的解决方案为我工作。 我在Cookie名称中添加了一个实例id,以提供线程安全的解决方案:

1
2
3
4
5
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...

客户

1
2
3
4
5
6
var checker = setInterval(()=>{
    if(document.cookie.indexOf(`fileDownloaded-${instanceId}`)>-1){
        alert('done');
        clearInterval(checker);
    }
},100);