자바 스크립트에서 이미지가로드되지 않는 경우 감지


104

이미지 경로가 실제 이미지로 연결되는지 확인하는 방법이 있습니까? 즉, 이미지가 Javascript에서로드되지 않을 때 감지합니다.

웹 앱의 경우 xml 파일을 구문 분석하고 이미지 경로 목록에서 HTML 이미지를 동적으로 만듭니다. 일부 이미지 경로가 더 이상 서버에 존재하지 않을 수 있으므로 HTML img 요소를로드하고 삭제하는 데 실패한 이미지를 감지하여 정상적으로 실패하고 싶습니다.

참고 JQuery 솔루션은 사용할 수 없습니다 (상사는 JQuery를 사용하고 싶지 않습니다. 예, 시작하지 않습니다). 이미지가로드 될 때 JQuery에서 감지하는 방법을 알고 있지만 실패했는지 여부는 알 수 없습니다.

img 요소를 만드는 코드는 img 경로가 이미지로드 실패로 이어지는 지 어떻게 감지 할 수 있습니까?

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

이 당신을 도울 수 stackoverflow.com/questions/1977871/... (그것의 jQuery를,하지만 여전히 옳은 길에 당신을 이끌 수 있음)
벤 리에게

이들 중 하나 시도 google.com/...
ajax333221

2
웃긴 @ ajax333221이 질문은 링크의 결과에서 첫 번째입니다. :)
SSH This

새로운 보스를 찾기 위해 JQuery 선택기를 작성하십시오. 인터넷은 큰 곳입니다.
JJS

답변:


115

다음 코드를 시도해 볼 수 있습니다. 그래도 브라우저 호환성을 보장 할 수 없으므로 테스트해야합니다.

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
리디렉션이 발생했는지 알 수있는 방법이 있는지 아십니까?
quickshiftin 2014

4
이미지를 가져 오는 서버에 따라 webKit (Epiphany, Safari, ...)에서는 작동하지 않습니다. 예를 들어 때때로 imgur는 존재하는 이미지 나 404 상태를 보내지 않으며이 경우 오류 이벤트가 트리거되지 않습니다.

이 문제는 "이미지를 찾을 수 없습니다."라는 메시지입니다. 응답 코드는 500 또는 403 또는 다른 것일 수 있습니다. 당신은 그것이 404라는 것을 모릅니다. 사실 그것은 당신이 거기에없는 이미지를로드하려고 시도하지 않을 것이기 때문에 그것이 404 일 가능성이별로 없습니다.
PHP Guru

1
직접 서명 대신 이벤트 처리기를 추가해야합니다
cdalxndr

50

대답은 좋지만 한 가지 문제가 있습니다. onload또는 onerror직접 할당 할 때마다 이전에 할당 된 콜백을 대체 할 수 있습니다. 이것이 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");

외부 리소스 로딩 프로세스는 비동기 적이므로 다음과 같은 약속과 함께 최신 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

2
여기에 화살표 기능에 대한 논의가있는 이유는 무엇입니까? 주제를 벗어났습니다. 특히 오래된 브라우저는 화살표 기능 (예 : Internet Explorer)을 지원하지 않기 때문에 대답은 괜찮습니다.
PHP Guru

29

이:

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

1
이것은 이미지 장애 복구 기술로 사용할 수있는 유용한 속성이지만 독자가 이해하는 데 더 자세한 응답이 도움이 될 것입니다.
설악

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

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 픽셀 의 정사각형 이미지 를 사용하십시오 .

TIP 2 : 인물 사진 과 함께 사용하려면object-position: 20% 50%;

background-img 전용 CSS

누락 된 배경 이미지의 경우 각 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 . 나는 당신이 필요로 정확히 무엇인지 모르겠지만, 그것은을위한 핸들러를 포함 당신이 사용하는 것이 다양한 기술을 사용하여 onload, onerror, onabort및 일반적인 타임 아웃을.

이미지로드는 비동기식이므로 이미지와 함께이 함수를 호출 한 다음 나중에 결과와 함께 콜백을 호출합니다.


-19

아래와 같이 :

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

if (!img.complete) {

//has picture
}
else //not{ 

}

3
아니. 이로 인해 일부 브라우저에서 이미지가 캐시되었는지 여부를 알 수 있지만로드 콜백이 없으면 브라우저가 해당 이미지에 대한 HTTP 요청을 시작할 수있는 기회를 제공 할 때까지 잠시도 기다리지 않습니다.
ChaseMoskal 2010 년

이것은 단지 무언가를 말하는 것입니다!
Hitmands

4
이미지 로딩은 비동기식입니다.
emil.c 2013 년

@ emil.c 어떤 이유로 항상 그런 것은 아닙니다. ChaseMoskal (누가 알려주지 않을 것입니다 ...) 옳습니다-이것은 JS 실행이 계속되기 전에 이미지가로드를 마친 경우에만 작동하며 캐시 될 때마다 발생하는 것처럼 보입니다.
tristan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.