<img>标签的onerror事件与404图片响应相关。

15

我正在从服务器加载图像,当图像不存在时,服务器将返回一个404响应以及一个200x200的PNG回退图像,上面写着"照片不可用"。

我想在客户端检测这种情况发生的时间。 我尝试使用onerror属性:

<img src="http://example.com/photo.jpg" onerror="console.log(this)" />

当服务器返回的404响应没有任何图像时,此代码才有效。由于我的404响应中有图像,因此onerror事件永远不会触发。

除了使用JavaScript预加载图像之外,是否有解决这个问题的方法?


如果 onerror 处理程序无效,您可以对 URL 进行 head 请求并检查是否返回 404。 - adeneo
在 JavaScript 中 Ping URL 并检查响应代码? - Lloyd Banks
是的,如果我找不到更好的方法,那么这些都是我会采取的选择。我更喜欢另一种解决方案,这样我就可以在标记中保留图像供非JavaScript用户使用。 - Brad
6个回答

1
一个解决方案是在服务器上找不到预期的图像时,不返回图像。相反,使用onerror事件稍后显示错误图像。
<img src="tttttttt.png" onerror="this.onerror=null;this.src='https://www.google.com/images/srpr/logo11w.png'" />

JSFiddle

参考: 使用jQuery/JavaScript替换损坏的图片


这对我来说不是一个选项,因为该服务除了我的应用程序之外还在其他地方使用,并且需要在其他情况下返回404图像。 - Brad

1

(在Brad指出我忽略的明显细节后进行了更新。)

我偶然发现了this,它似乎可以正确地触发onerror():

<html>
    <head>
        <script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
        <script type="text/javascript">
        (function($) {
            $.fn.errimg = function(options) {
                return this.each(function() {
                    if (this.tagName.toLowerCase() != 'img')
                        return;         

                    // store current img for error reference
                    var $_orig = $(this);
                    // create "production" image
                    var $newImg = $_orig.clone()
                        .attr('src', $_orig.data('src') || '')
                        .one('error', function() {
                            $(this).parent()
                                .empty()
                                .append($_orig);
                        });
                    // replace current img
                    $_orig.parent().empty().append($newImg);
                });
            };
        })(jQuery);         

        $(function() {
            $('.js_img img').errimg();
        });
        </script>
    </head> 

    <body class="js_img">
        <img id="testimgbad" src="http://img4.homefinder.com/i/00000000-0000-0000-0000-000000000000/w200-h-q" onerror="console.log('errored out');" />
    </body> 

</html>

这根本不是事实。你绝对可以使用404发送数据,而且这很常见。在我的情况下,404是正确的响应状态码,并返回了设计好的图像。我只需要在特定应用程序中在客户端检测它即可。 - Brad
你可以给我一个出现这种情况的链接吗? 我并不是在暗示你错了,我只是从未经历过或更准确地说亲眼见证浏览器会这样做。 - Patrick Webster
把它看作是任何其他错误文档。人们经常使用自定义404页面。这与此不同之处在于内容类型是专门的。您可以在JSON API服务器上看到类似的东西,其中发送了一个漂亮的JSON错误响应,而不是HTML 404页面。 - Brad
是的,我在发布上述内容后刚刚阅读了有关此事的规格说明。由于浏览器必须预先读取以查找发送到呈现图像的内容类型,因此它无法像普通的404一样退出,因此状态错误被忽略。我真的希望http2能够解决从基于1999年标准开发浏览器的2015年中出现的特殊情况异常。不过,似乎仍然应该有另一种方法来访问该状态,可能是通过DOM阴影元素。让我看看还能想出什么来,以节省每次加载图像时都要复制的工作。 - Patrick Webster
这是HTTP/1.0的一个完全正常的用例。浏览器确实会抛出错误,因为我可以在控制台中看到它。只是它不会为图像触发onerror,我同意这是一个错误,但在几个浏览器中非常一致。我在相关问题上添加赏金的原因是我认为解决方法可能是捕获所有错误(就像开发者工具一样),然后搜索DOM以删除具有匹配src属性的有问题的图像元素。其他人已经发布了解决方案,我只是还没有测试过。 - Brad
显示剩余3条评论

0
我采用的解决方法是通过ajax调用内部方法,该方法使用httpclient检查图像是否返回404预制页面。如果是(任何状态404),则返回我的匿名图像,否则返回字符串本身。

-1
如果您确定现有图像和404图像之间的尺寸不同,您可以使用该信息来执行其他技巧。
例如,您想显示可用的最大16:9 Youtube缩略图。如果获取的缩略图不存在,Youtube会返回一个120px x 90px的“404-image”。因此,让我们获取maxresdefault缩略图,并显示mqdefault缩略图作为备用。
<img src="https://img.youtube.com/vi/{id}/maxresdefault.jpg" onload="if (this.naturalWidth === 120) {this.src = this.currentSrc.replace('maxresdefault', 'mqdefault');}">

-1
你可以使用onload函数代替onerror,并检查图像是否已加载(如果你在开始时了解该图像的某些信息)。
你还可以测量这种情况预计会发生多少次,因为你正在为可能不必要的每个可能的图像注册某种侦听器。

-2

我可能有点晚,但我也遇到了这种情况,我想出的解决方案是在加载时使用ajax,然后检查ajax是否失败。为了简洁起见,我在这里使用了jQuery。希望能帮助到某些人。

$('#image').on('load',function(e){
   var self = this;
   $.get($(this).attr('src'))
    .then(function(){
     // do nothing
    },function(){
       console.log('do something if it has error');
    });
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接