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


103

有没有一种方法可以确定图像路径是否指向实际图像,即检测图像何时无法在Javascript中加载。

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

注意JQuery解决方案将无法使用(老板不想使用JQuery,是的,我知道我不入门)。我知道在JQuery中一种检测何时加载图像的方法,但不知道它是否失败。

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

var imgObj = new Image();  // document.createElement("img");
imgObj.src = src;

这可能对您有帮助:stackoverflow.com/questions/1977871/…(它是jQuery,但仍可能引导您走上正确的道路)
Ben Lee

请尝试以下的一个google.com/...
ajax333221

2
有趣的@ ajax333221这个问题首先出现在您的链接结果中:)
SSH

编写一个JQuery选择器以找到新的老板...互联网是一个很大的地方。
JJS

Answers:


113

您可以尝试以下代码。不过,我不能保证浏览器的兼容性,因此您必须进行测试。

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

我对耐jQuery的老板表示同情!


2
知道是否有办法告诉它是否遇到重定向吗?
quickshift

4
这在webKit(Epiphany,Safari等)上不起作用,具体取决于要从中获取图像的服务器。例如,有时imgur不发送存在的图像或404状态,并且在这种情况下不会触发错误事件。

问题是您的消息“找不到该图像”。响应代码可以是500或403或其他。您不知道它是404。实际上,它不太可能是404,因为您可能不会尝试加载不存在的图像。
PHP专家

1
应该添加事件处理程序,而不是直接asignment
cdalxndr

50

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

让我重写一下答案。

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

由于外部资源加载过程是异步的,因此最好使用带有承诺的现代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');
    }

);

2
也许我错过了一些东西,但是如果“ tester”是刚刚创建的,该赋值(tester.onload = ..)如何替换回调?即使代码的某些晦涩部分将事件添加到创建的每个图像中,我们也不希望保留这些事件以检测图像是否存在。
jvilhena

1
你是绝对正确的。在这种特殊情况下,这可能不是问题,因为很有可能不会被替换。但是,总的来说,添加事件侦听器比直接分配方法更好。
emil.c

1
@JohnWeisz Arrow函数是匿名的,因此很难调试,请谨慎使用它们。
emil.c

10
@GifCo我不愿意继续与您进行此类讨论。你的语言让我感到生气。如果您认为我的答案不正确或不完整,请提出更改建议并解释您的理由。如果您认为某事不好,建议您自己回答一个好的做法。
emil.c

1
为什么在这里讨论箭头功能?这是题外话。答案很好,特别是因为旧的浏览器不支持箭头功能(例如Internet Explorer)。
PHP专家

29

这个:

<img onerror="this.src='/images/image.png'" src="...">

1
尽管这是可以用作图像故障转移技术的有用属性,但是更详细的响应将有助于读者理解它。
sorak

1
太短了,太有用了!为了将其隐藏起来:<img src="your/path/that/might/fail.png" onerror="$(this).hide();"/>
J0ANMM

2
@sorak的评论让我厌恶地笑了。这是正确的答案。
user3751385

@ J0ANMM隐藏图像的另一种方法是添加一个空的alt属性:<img alt =“” src =“ yourpicture.png”>
Rick Glimmer

优秀的!而不是故障转移到图像,我将文本打印为onerror =“ this.alt ='无效图像,请使用链接^'”
出汗

6
/**
 * 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;
});

4

jQuery + CSS for img

使用jQuery,这对我有用:

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

而且我可以使用以下CSS3属性在网站上的任何位置使用此图片,而不管其大小如何:

img.no-img {
    object-fit: cover;
    object-position: 50% 50%;
}

提示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');

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

Apache服务器端

另一种解决方案是先使用Apache检测丢失的图像,然后再将其发送到浏览器并通过默认的no-img.png内容对其进行替换。

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

3

这是我为另一个答案编写的函数:Javascript Image Url Verify。我不知道这是否是你所需要的东西,但它使用了包括处理程序的各种技术,你会使用onloadonerroronabort和一般的超时。

由于图像加载是异步的,因此您可以在图像上调用此函数,然后稍后再使用结果调用回调。


-19

就像下面这样:

var img = new Image(); 
img.src = imgUrl; 

if (!img.complete) {

//has picture
}
else //not{ 

}

3
不。在某些浏览器中,这可能会提示您是否缓存了图像-但是在没有加载回调的情况下,您甚至不需要等待片刻就可以使浏览器有机会对该图像发起HTTP请求。
ChaseMoskal

这只是为了说些什么!
Hitmands

4
图像加载是异步的。
emil.c

@ emil.c并非总是出于某种原因。ChaseMoskal(不会让我通知...)正确-仅当图像在JS执行继续之前完成加载时才起作用,这似乎在缓存时发生。
特里斯坦(Tristan)2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.