Iframe.readyState 在 chrome 中不起作用

IT技术 javascript jquery asp.net html iframe
2021-02-21 04:13:43

我即时创建了一个 Iframe,并将下载二进制文件(xls、doc ...)的页面设置为 url 在下载文件时,我会播放动画。什么时候没有,我隐藏它。

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

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 中有效,在内容是二进制文件时无效

if ($.browser.mozilla || $.browser.webkit ) {
    iframe.onload = function showProgressAnimation() {
        animation.style.display = 'none';
        progressBar.hide();
        $('#page').show();
    }
}
// IE
else{
     window.setTimeout(showProgressAnimation, 1000);
}
4个回答

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

这是一个简单的例子,可以工作

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/

@LeeMeador 谢谢你的留言。如果您有非工作情况的解决方案,请与我们分享。pdf 可能是由 adobe acrobat 的插件处理的,也许这是导致无法正常工作的问题。
2021-04-24 04:13:43
对于我拥有的版本,FF 和 Chrome 似乎对 PDF 内容使用自己的代码。IE 和 Safari 似乎使用 Acrobat 插件。
2021-04-24 04:13:43
重新审视一下,我坚信您需要在设置 src 之前分配 onload。另外为什么将函数括在括号中?
2021-05-05 04:13:43
如果 url 是 PDF 或更准确的 MIME 类型应用程序/pdf,则在 Chrome 中不起作用。适用于 IE 9、Windows Safari 和 FireFox。FF 和 Chrome 的版本几乎都是最新的。Safari 已经有几个月的历史了。在所有四个中都可以与test.com一起使用。
2021-05-06 04:13:43
由于在 Chrome 中下载文件时不会触发 onLoad 事件,因此有一种技术可以使用 cookie 来检查它是否已加载。有一个插件可以很好地实现该技术:johnculviner.com/...
2021-05-18 04:13:43

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

服务器

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

客户

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

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

此问题的评论中找到原因,如果您使用此解决方案,则需要设置cookie的路径,否则将无法正常工作。
2021-04-28 04:13:43
Set-Cookie:download=1518612276937奇怪的是,我cookie:在下一个请求的标题中包含它它与 httponly cookie 一样工作,但没有使用该选项。这是在谷歌浏览器中。也许我会问另一个问题。
2021-05-03 04:13:43
但是 cookie 是在 iframe 完成加载 ( iframe.contentDocumement.readyState == "complete")的同时设置的,也就是在第一个数据发送到客户端时。(我在 php 中使用刷新,因为否则我没有在浏览器中获得进度,最后只有一次)。
2021-05-04 04:13:43
我在从 php 脚本下载二进制文件时使用此解决方案,并且 document.cookie 永远不会获取在 php 中设置的值,开发人员工具显示正确的 set-cookie 标头但永远不会更新 document.cookie。
2021-05-14 04:13:43

请试试这个——你真的是在一行一行地混合 dom 和 jQuery

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); // 
如果 URL 加载 PDF(应用程序/pdf),这在 FireFox 或 Chrome(它采用加载选项)中不起作用,但在 Windows Safari 中起作用。它适用于 IE 9,但打印两次(一次用于“交互式”,一次用于“完整”),但是打印的页面是空白的。
2021-05-16 04:13:43

Sarkiroka 的解决方案对我有用id在 cookie 名称中添加了一个实例以提供线程安全的解决方案:

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...

客户

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