iframe.readyState 在 chrome 中不起作用

Posted

技术标签:

【中文标题】iframe.readyState 在 chrome 中不起作用【英文标题】:Iframe.readyState does not work in chrome 【发布时间】:2012-12-06 20:06:52 【问题描述】:

我动态创建一个 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);

【问题讨论】:

我知道这听起来很简单,但请尝试从代码中删除 if ($.browser.mozilla) 并重试。至少对我来说这是有效的。 onload 是我使用并使其工作的。 为什么不$("iframe").on("load",function () animation.style.display = 'none'; progressBar.hide(); $('#page').show(); ); 控制台有话要说? @Aristos 我做到了,但没有用。你试过铬吗?使用我现在拥有的完整跨浏览器代码更新了问题。 在 Chrome 上是的,我使用 chrome。你有什么错误吗? 您是否看到您使用visible 隐藏它,但您使用display 显示它?这必须相同才能工作。在onload 上发出警报以仔细检查未调用的情况。 【参考方案1】:

您可以使用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/

【讨论】:

如果 url 是 PDF 或更准确地说是 mime 类型 application/pdf,则在 Chrome 中不起作用。适用于 IE 9、Windows Safari 和 FireFox。 FF 和 Chrome 的版本几乎是最新的。 Safari 已经几个月了。在所有四个中都可以与 test.com 一起使用。 @LeeMeador 谢谢你的来信。如果您有非工作案例的解决方案,请与我们分享。 pdf 可能是由 adobe acrobat 的插件处理的,这可能是导致无法正常工作的问题。 对于我拥有的版本,似乎 FF 和 Chrome 使用自己的代码来处理 PDF 内容。 IE 和 Safari 似乎使用 Acrobat 插件。 刚刚重温一下,我坚信您需要在设置 src 之前分配 onload。还有为什么要把函数括在括号中? 由于在 Chrome 中下载文件时不会触发 onLoad 事件,因此有一种技术可以使用 cookie 来检查它是否已加载。有一个插件可以很好地实现该技术:johnculviner.com/…【参考方案2】:

可下载的文件内容不会触发 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 解析器。

【讨论】:

我在从 php 脚本下载二进制文件时使用此解决方案,但 document.cookie 从未获得 php 中设置的值,开发人员工具显示正确的 set-cookie 标头但 document.cookie 从未更新。跨度> Set-Cookie:download=1518612276937 奇怪的是我在下一个请求的cookie: 标头中有它。它与 httponly cookie 一样工作,但未使用该选项。这是在谷歌浏览器中。也许我会问另一个问题。 在this question的评论中找到原因,如果使用此方案需要设置cookie的路径,否则无法使用。 但是 cookie 是在 iframe 完成加载 (iframe.contentDocumement.readyState == "complete") 的同时设置的,也就是第一个数据发送到客户端时。 (我在php中使用flush,否则我没有在浏览器中获得progrees,最后只有一次)。【参考方案3】:

请试试这个 - 你真的在逐行混合 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 中工作,但打印两次(一次用于“交互式”,一次用于“完成”)但是打印的页面是空白的。【参考方案4】:

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

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);

【讨论】:

以上是关于iframe.readyState 在 chrome 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

VCF 文件缺少强制性标题行(“#CHROM...”)

Mac中的Python安装selenium,结合chrom及chromdriver使用

Chrom 浏览器一些命令

chrom插件1

sh refseq chroms dict convert

chrom浏览器-F12使用方法二