检测何时无法在Javascript中加载图像

saz*_*azr 88 javascript onerror imagesource image-loading

有没有办法确定图像路径是否会导致实际图像,即检测到图像无法在Javascript中加载.

对于Web应用程序,我正在解析xml文件并从图像路径列表中动态创建HTML图像.服务器上可能不再存在某些映像路径,因此我希望通过检测哪些映像无法加载并删除该HTML img元素来优雅地失败.

注意JQuery解决方案无法使用(老板不想使用JQuery,是的,我知道不要让我开始).我知道在JQuery中检测图像何时加载的方法,但不知道它是否失败.

我的代码创建img元素,但我如何检测img路径是否导致无法加载图像?

var imgObj = new Image();  // document.createElement("img");
imgObj.src = src;
Run Code Online (Sandbox Code Playgroud)

Nik*_*hil 101

您可以尝试以下代码.我不能担保浏览器兼容性,所以你必须测试它.

function testImage(URL) {
    var tester=new Image();
    tester.onload=imageFound;
    tester.onerror=imageNotFound;
    tester.src=URL;
}

function imageFound() {
    alert('That image is found and loaded');
}

function imageNotFound() {
    alert('That image was not found.');
}

testImage("http://foo.com/bar.jpg");
Run Code Online (Sandbox Code Playgroud)

我对jQuery抗性老板的同情!

  • 这不适用于webKit(Epiphany,Safari,...),具体取决于您从中获取图像的服务器.例如,有时imgur不发送存在的图像也不发送404状态,并且在这种情况下不会触发错误事件. (4认同)
  • 知道是否有办法告诉它是否遇到重定向吗? (2认同)

emi*_*l.c 36

答案很好,但它引入了一个问题.无论何时分配onloadonerror直接分配,它都可以替换先前分配的回调.这就是为什么有一个很好的方法,就像在MDN 所说的那样"在被调用的EventTarget上注册指定的监听器".您可以在同一事件中注册任意数量的侦听器.

让我稍微改写一下答案.

function testImage(url) {
    var tester = new Image();
    tester.addEventListener('load', imageFound);
    tester.addEventListener('error', imageNotFound);
    tester.src = url;
}

function imageFound() {
    alert('That image is found and loaded');
}

function imageNotFound() {
    alert('That image was not found.');
}

testImage("http://foo.com/bar.jpg");
Run Code Online (Sandbox Code Playgroud)

因为外部资源加载过程是异步的,所以使用具有promise的现代JavaScript会更好,例如以下内容.

function testImage(url) {

    // Define the promise
    const imgPromise = new Promise(function imgPromise(resolve, reject) {

        // Create the image
        const imgElement = new Image();

        // When image is loaded, resolve the promise
        imgElement.addEventListener('load', function imgOnLoad() {
            resolve(this);
        });

        // When there's an error during load, reject the promise
        imgElement.addEventListener('error', function imgOnError() {
            reject();
        })

        // Assign URL
        imgElement.src = url;

    });

    return imgPromise;
}

testImage("http://foo.com/bar.jpg").then(

    function fulfilled(img) {
        console.log('That image is found and loaded', img);
    },

    function rejected() {
        console.log('That image was not found');
    }

);
Run Code Online (Sandbox Code Playgroud)

  • @GifCo我不愿意继续与你进行这样的讨论.我觉得被你的语言冒犯了.如果您认为我的答案不正确或不完整,请提出更改并解释您的推理.如果您认为某些事情是不好的做法,请用您自己的答案建议一个好的做法. (9认同)
  • 你是绝对正确的。在这种特殊情况下,它可能不是问题,因为它很可能不会被替换。但是,一般来说,添加事件侦听器比直接分配方法更好。 (3认同)
  • 为什么这里要讨论箭头函数呢?这是题外话。答案很好,尤其是因为旧浏览器不支持箭头功能(例如 Internet Explorer)。 (3认同)
  • 也许我遗漏了一些东西,但是如果“测试器”刚刚创建,那么分配(tester.onload=..)如何替换回调?即使代码的某些晦涩部分为创建的每个图像添加了一个事件,我们也不会为了检测图像是否存在而保留这些事件。 (2认同)

小智 18

这个:

<img onerror="this.src='/images/image.png'" src="...">
Run Code Online (Sandbox Code Playgroud)

  • 好短好用!为了隐藏它:`&lt;img src="your/path/that/might/fail.png" onerror="$(this).hide();"/&gt;` (4认同)
  • 注意:如果这个“image.png”不存在,它将导致无限错误循环。你可以这样做来避免它: `&lt;img onerror="this.onerror=null;this.src='/images/image.png'" src="..."&gt; ` (4认同)
  • @sorak 的评论让我厌恶地笑了。这是正确答案。 (3认同)
  • 出色的!我没有故障转移到图像,而是打印此文本 onerror="this.alt='Not Valid Image, Use Link ^'" (2认同)

hol*_*erd 8

/**
 * Tests image load.
 * @param {String} url
 * @returns {Promise}
 */
function testImageUrl(url) {
  return new Promise(function(resolve, reject) {
    var image = new Image();
    image.addEventListener('load', resolve);
    image.addEventListener('error', reject);
    image.src = url;
  });
}

return testImageUrl(imageUrl).then(function imageLoaded(e) {
  return imageUrl;
})
.catch(function imageFailed(e) {
  return defaultImageUrl;
});
Run Code Online (Sandbox Code Playgroud)


Mel*_*man 5

用于 img 的 jQuery + CSS

使用 jQuery,这对我有用:

$('img').error(function() {
    $(this).attr('src', '/no-img.png').addClass('no-img');
});
Run Code Online (Sandbox Code Playgroud)

我可以在我的网站上的任何地方使用这张图片,无论它的大小如何,具有以下 CSS3 属性:

img.no-img {
    object-fit: cover;
    object-position: 50% 50%;
}
Run Code Online (Sandbox Code Playgroud)

提示 1:使用至少 800 x 800 像素的方形图像

提示2:用于人物肖像,使用object-position: 20% 50%;

CSS 仅用于 background-img

对于缺少的背景图片,我还在每个background-image声明中添加了以下内容:

background-image: url('path-to-image.png'), url('no-img.png');
Run Code Online (Sandbox Code Playgroud)

注意:不适用于透明图像。

阿帕奇服务器端

另一种解决方案是在发送到浏览器之前使用 Apache 检测丢失的图像并用默认的 no-img.png 内容替换它。

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} /images/.*\.(gif|jpg|jpeg|png)$
RewriteRule .* /images/no-img.png [L,R=307]
Run Code Online (Sandbox Code Playgroud)


小智 5

更多关于 Rafael Martins 的答案,如果您使用 React,请使用以下代码:

<img
  src="https://example.com/does_not_exist.png"
  onError={(e) => {
    e.currentTarget.src = "https://example.com/default.png"
  }}
/>
Run Code Online (Sandbox Code Playgroud)