【问题标题】:How to get HTTP status code of <img> tags如何获取 <img> 标签的 HTTP 状态码
【发布时间】:2011-11-13 00:23:16
【问题描述】:

我有一个页面,其中包含大量图像,这些图像是根据用户操作在服务器端生成的。当图像加载成功时我很高兴,但是当服务器出现错误时,我必须根据发生的错误采取行动。

例如:

  • 500 码:做这件事。
  • 503 代码:做那件事

等等。

那么,我的问题:有没有办法在“img”标记错误事件处理程序中获取状态码?

【问题讨论】:

  • 您为什么要在客户端处理此类问题?为什么不让服务器正确处理这些图像?
  • @Raynos 情况是这样的:图像是在服务器上动态创建的,但这需要很长时间,这意味着当浏览器请求它们时,其中一些不会准备好。同时,服务器端可能会发生一些严重错误,并且根本没有图像。因此,基于 http 状态,我必须再次向服务器请求图像,或者只是通知用户错误。
  • 不,你还是做错了。你有一个 HTTP 服务器,当你收到一个图像的传入 GET 请求时,你可以“等待”它准备好。如果发生严重错误,您可以返回“严重错误”图像。
  • @Raynos 不幸的是,我只在前端工作,无权访问后端。我对问题的条件不满意。据我所知,服务器无法承受大量打开的连接,所以我只能询问图像是否准备好,而不是等待图像准备好。

标签: javascript image http-status-codes


【解决方案1】:

不,无法从 JavaScript 中 img 标记发出的请求中获取 HTTP 状态。

您可以编写一个 firefox 插件、chrome/safari 扩展来做到这一点。

另一种方法是使用 AJAX 加载图像(不使用 img 标签)。您可以从 Ajax 请求中获取 Http 状态代码。

【讨论】:

  • 插件不可接受。 AJAX 好像没问题,但是我应该通过 AJAX 获取什么样的数据呢?我可以检索图像数据,但不能使用它来创建 img 元素。
  • 您很可能需要将其作为数据 url 发送。您可能需要找到某种可以在服务器端生成数据 url 的库。然后,一旦他们到达,只需将 img 的 src 设置为数据 url。这将增加加载图像的大量开销。真正的解决方案可能是修复服务器,使其始终成功发送图像。
  • Ajax 不是一个很好的替代品,以防万一,您想要加载的图像被放置在外部域中。 2016 年这个问题有什么新消息吗?
【解决方案2】:

您无法通过这种方式检查 HTTP 状态。但是,您可以使用 naturalWidth 属性检查图像是否已加载。

if (img.naturalWidth === 0) {
    // do sth
}

希望对您有所帮助。

【讨论】:

  • 对于阅读此页面的任何人,并非所有浏览器都支持 naturalWidth 属性。这个属性也很敏感——你应该只在图像加载后才尝试读取它。 (stackoverflow.com/questions/1645166/…) 我希望这会有所帮助。 :)
  • @Axle 您指的是 09 年的帖子。现在它适用于所有最新的浏览器版本。
  • 我碰巧在某个需要支持旧浏览器(例如 IE 7 和 IE 8)的地方工作。我敢肯定还有其他人遭受类似的命运。相信我,尖叫着“好吧,他们应该更新他们损坏的工具!”从来没有把我带到任何地方。 :P
  • @Axle 好吧,因为强制升级到 IE9,所以没有 IE7 或 8。如果有人有旧版本,则意味着它是盗版 Windows 版本 :-) 无论如何,我(和我工作的公司)不关心任何不是最新的东西。事实上,我只在谷歌浏览器中测试东西,当工作正常时。
  • @Axie,Wojciech,img.complete 是您应该查看图像是否已加载,或者为了保证兼容性,您可以附加到 onload 事件。
【解决方案3】:

您可以结合这两种技术来获得 img.status:

<img src="/no.img" onerror="error(this)">

function error(img) {
   var r = makeXMLHttpRequestAgain(img.src);
   if (r.status === 500) img.src = '/e500.img';
   if (r.status === 503) img.src = '/e503.img';
}

【讨论】:

  • makeXMLHttpRequestAgain的来源?
  • @Tino,makeXMLHttpRequestAgain 尚未实现。思路是让 XMLHttpRequest 获取状态码。
  • 我的问题是,&lt;img&gt; 加载了状态代码 200(通常,除了少数情况),而 XMLHttpRequest 返回 402 由于 XMLHttpRequestfetch 的工作方式.该网页在我的控制之下,而&lt;img&gt;-site 不在。 &lt;img&gt; 站点防止链接来自未经授权站点的图像。我的网站已获得授权。 .decode() 也不起作用,因为 .decode() 经常失败,而 &lt;img&gt; 看起来还可以。 .naturalWidth 有效,但没有提示 &lt;img&gt; 失败的原因或方式,即如果是402404408500 等。AFAICS 只有浏览器扩展才能解决此问题..
  • 在您的情况下,免费生成 ssl 证书可以解决您的问题。
  • 添加额外的 SSL 并没有帮助,因为它已经存在。 &lt;img&gt;-site(不在我的控制之下)就像 https://images.example.net/image.jpg 而我的网站(在我的控制之下)就像 https://www.example.org/img.html
【解决方案4】:
 function loadBinaryImageAndInsertToImgTag(imgElement, imageUrl) {
        let xhr = getXMLHttpRequest();
        xhr.onreadystatechange = ProcessResponse;
        xhr.open("GET", imageUrl, true);
        xhr.overrideMimeType('text/plain; charset=x-user-defined');
        xhr.send(null);

        function getXMLHttpRequest() {
            let xhr = null;

            if (window.XMLHttpRequest || window.ActiveXObject) {
                if (window.ActiveXObject) {
                    try {
                        xhr = new ActiveXObject("Msxml2.XMLHTTP");
                    } catch (e) {
                        xhr = new ActiveXObject("Microsoft.XMLHTTP");
                    }
                } else {
                    xhr = new XMLHttpRequest();
                }
            } else {
                alert("Your browser does not support XMLHTTP");
                return null;
            }
            return xhr;
        }

        function ProcessResponse() {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    imgElement.src = "data:image/jpeg;base64," + encode64(xhr.responseText);
                    imgElement.style.display = "";
                } else {
                    alert("Error retrieving data!");
                }
            }
        }

        function encode64(inputStr) {
            let b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
            let outputStr = "";
            let i = 0;

            while (i < inputStr.length) {
                let byte1 = inputStr.charCodeAt(i++) & 0xff;
                let byte2 = inputStr.charCodeAt(i++) & 0xff;
                let byte3 = inputStr.charCodeAt(i++) & 0xff;
                let enc1 = byte1 >> 2;
                let enc2 = ((byte1 & 3) << 4) | (byte2 >> 4);
                let enc3, enc4;
                if (isNaN(byte2)) {
                    enc3 = enc4 = 64;
                }
                else {
                    enc3 = ((byte2 & 15) << 2) | (byte3 >> 6);
                    if (isNaN(byte3)) {
                        enc4 = 64;
                    }
                    else {
                        enc4 = byte3 & 63;
                    }
                }
                outputStr += b64.charAt(enc1) + b64.charAt(enc2) + b64.charAt(enc3) + b64.charAt(enc4);
            }
            return outputStr;
        }
    }

【讨论】:

  • 为什么是encode64 而不是btoa
【解决方案5】:

你必须在图像上添加一个事件监听器:

以 jQuery 为例:

$('#your_image')
    .error(function(e) {
        //add your unhappy code here

        //unbind if needed
        $(this).unbind('error');
    })
    .load(function(e) {
        //add your happy code here

        //unbind if needed
        $(this).unbind('load');
    })
    ;

【讨论】:

  • 请注意,从API for .error():“事件处理程序必须附加之前浏览器触发错误事件,这就是为什么示例在附加处理程序之后设置 src 属性。" (强调我的)。
  • 随便扔点jQuery,肯定能解决问题!
猜你喜欢
  • 2015-06-08
  • 1970-01-01
  • 1970-01-01
  • 2019-07-22
  • 2011-02-26
  • 1970-01-01
  • 1970-01-01
  • 2011-10-18
  • 2018-10-28
相关资源
最近更新 更多