检测iframe加载错误

时间:2012-11-04 19:59:33

标签: html5 iframe mobile-safari

我正在使用src属性将用户选择的页面加载到iframe中。如果加载失败,我想以对用户有意义的方式报告问题。根据{{​​3}},iframe通常不会支持错误。

该页面可能来自用户的域名,而不是我的域名,因此我无法查看iframe的内容。

如果加载成功,我可以设置超时并从我的onload处理程序取消它,但是需要长时间超时以避免错误报告,同时我的iPhone上的Safari显示警告可能会混淆用户。即使这对Kindle Fire浏览器也不起作用 - 无论加载是否成功,它都会向我的处理程序提供加载事件。

我可以使用任何事件来检测故障吗?有没有办法抑制默认的Safari行为?我能判断加载尝试是否失败的任何方式? (如果我可以这样做,我可以使用更短的超时和轮询,直到解决了加载尝试。)

我可以要求使用最新的浏览器,但想要一个可以在尽可能多的智能手机和平板电脑中移植的解决方案。

我已经测试了AJAX Get的想法,但遗憾的是它不起作用。跨域AJAX获取任意URI会导致异常,无论目标是否存在且是否可以加载到iframe中。

3 个答案:

答案 0 :(得分:10)

您可以将iframe和/或ajax请求设置为始终调用您控制的页面(即:loader.php),通过get发送loader.php用户请求的页面。从loader.php,使用curl甚至只是file_get_contents来获取外部页面。如果请求无法返回到loader.php,您可以检查错误,并返回您想要显示的iframe。

虽然我的示例引用了php的使用,但各种脚本语言都支持curl。它可能比您可能拥有的其他解决方案更复杂,但是可以让您访问响应标头以及解决页面加载失败的原因。

答案 1 :(得分:2)

正如您所暗示的那样,当您尝试查询iframe内的任何内容(如果它位于单独的域中)时,您将面临同源策略类型限制。

您可以向iframe的URL发出AJAX GET请求,然后再将其传递到框架的src。如果您没有从AJAX调用中获得HTTP 200响应,那么该站点也将无法在该帧内加载。

这会增加整个过程的开销,并且仅在您检查 iframe的文档是否是真正有效的URL时才有用。如果您需要知道何时 iframe文档已完全加载,那将无济于事。

如果您需要知道iframe何时加载,并且它在外部域上,那么我相信您没有其他选择,只能要求将一些代码添加到这些外部站点以通知父页面他们'已成功加载。

或者,如果这样做有意义,请让最终用户点击链接以标记内容未正确加载。

答案 2 :(得分:-1)

晚会,但我设法破解了它:

起初,我想像其他人一样做一个AJAX调用,除了它最初对我没用,因为我使用了jQuery。如果你执行XMLHttpRequest,它可以很好地工作:

var url = http://url_to_test.com/
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status != 200) {
        console.log("iframe failed to load");
    }
};
xhttp.open("GET", url, true);
xhttp.send();

修改
因此,这种方法可以正常工作,除非它有很多假阴性(由于交叉原始的malarky而拾取了很多会在iframe中显示的东西)。我解决这个问题的方法是在服务器上执行CURL / Web请求,然后检查响应标头a)如果网站存在,b)标头是否设置了x-frame-options

如果您运行自己的网络服务器,这不是问题,因为您可以自己进行api调用。

我在node.js中的实现:

app.get('/iframetest',function(req,res){ //Call using /iframetest?url=url - needs to be stripped of http:// or https://
   var url = req.query.url; 
    var request = require('https').request({host: url}, function(response){ //This does an https request - require('http') if you want to do a http request
        var headers = response.headers;
        if (typeof headers["x-frame-options"] != 'undefined') {
            res.send(false); //Headers don't allow iframe
        } else {
            res.send(true); //Headers don't disallow iframe
        }
    });
    request.on('error',function(e){
       res.send(false); //website unavailable
    });
    request.end();
});