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

IT技术 javascript image
2021-01-30 06:24:00

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

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

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

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

var imgObj = new Image();  // document.createElement("img");
imgObj.src = src;
6个回答

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

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 的老板表示同情!

应该添加事件处理程序而不是直接分配
2021-03-20 06:24:00
知道是否有办法判断它是否遇到重定向?
2021-03-29 06:24:00
这在 webKit(Epiphany, Safari, ...) 上不起作用,具体取决于您从中获取图像的服务器。例如,有时 imgur 不会发送存在的图像,也不会发送 404 状态,并且在这种情况下不会触发错误事件。
2021-04-04 06:24:00
问题在于您的消息“未找到该图像”。响应代码可能是 500 或 403 或其他。您不知道这是 404。事实上,它不太可能是 404,因为您可能不会尝试加载不存在的图像。
2021-04-06 06:24:00

答案很好,但它引入了一个问题。每当您分配onloadonerror直接分配时,它可能会替换之前分配的回调。这就是为什么有一个很好的方法可以“在它被调用的 EventTarget 上注册指定的侦听器”,正如他们在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");

因为外部资源加载过程是异步的,所以使用带有 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');
    }

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

这:

<img onerror="this.src='/images/image.png'" src="...">
虽然这是一个有用的属性,可以用作图像故障转移技术,但更详细的响应将有助于读者理解它。
2021-03-16 06:24:00
注意:如果这个“image.png”没有退出,它会导致一个无限的错误循环。你可以这样做来避免它: <img onerror="this.onerror=null;this.src='/images/image.png'" src="...">
2021-03-24 06:24:00
@J0ANMM 另一种隐藏图像的方法是添加一个空的 alt 属性:<img alt="" src="yourpicture.png">
2021-03-26 06:24:00
优秀的!而不是故障转移到图像我打印此文本 onerror="this.alt='Not Valid Image, Use Link ^'"
2021-03-29 06:24:00
好短好用!为了隐藏它:<img src="your/path/that/might/fail.png" onerror="$(this).hide();"/>
2021-04-02 06:24:00
/**
 * 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;
});

用于 img 的 jQuery + CSS

使用 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]