Sprawdź, czy obraz istnieje na serwerze przy użyciu JavaScript?


124

Czy za pomocą javascript można sprawdzić, czy zasób jest dostępny na serwerze? Na przykład mam obrazy 1.jpg - 5.jpg załadowane na stronę html. Chciałbym wywoływać funkcję JavaScript mniej więcej co minutę, która z grubsza wykonałaby następujący kod zdrapki ...

if "../imgs/6.jpg" exists:
    var nImg = document.createElement("img6");
    nImg.src = "../imgs/6.jpg";

Myśli? Dzięki!

Odpowiedzi:


209

Możesz użyć czegoś takiego:

function imageExists(image_url){

    var http = new XMLHttpRequest();

    http.open('HEAD', image_url, false);
    http.send();

    return http.status != 404;

}

Oczywiście możesz użyć jQuery / podobny do wykonania żądania HTTP.

$.get(image_url)
    .done(function() { 
        // Do something now you know the image exists.

    }).fail(function() { 
        // Image doesn't exist - do something else.

    })

4
Ale nazwa funkcji nie powinna brzmieć fileExists, ponieważ działa to na .js .css .html lub innym publicznie dostępnym pliku.
KR

1
Funkcja jest niesamowita. Umieściłem to w swojej kolekcji :) Pomyślałem, fileExistsże będzie lepsza nazwa, ponieważ ta funkcja nie sprawdza, czy obraz istnieje na serwerze. Sprawdza, czy plik jest dostępny z serwera. Nie ma możliwości sprawdzenia, czy ten plik faktycznie jest obrazem. Może to być .pdf, .html, jakiś losowy plik o zmienionej nazwie na * .jpg lub * .png. Jeśli coś kończy się na .jpg, nie oznacza to, że jest to obraz w 100% :)
KR

9
To się nie powiedzie, chyba że dostęp do zasobu jest dozwolony zgodnie z regułami CORS. Korzystanie z Imageobiektu nie podlega temu ograniczeniu. Jedyną zaletą jest to, że faktycznie nie pobierze obrazu.
Alnitak

8
problem między domenami.
Amit Kumar,

2
To działa, ale pamiętaj, że przetwarzanie żądania zajmuje więcej czasu i nie jest najlepszym rozwiązaniem. Ponadto nie działa na cross origin (zdecydowanie w chrome), więc nie możesz go używać na protokole file: ///, co oznacza brak lokalnego użycia.
Cameron

119

Możesz użyć podstawowego sposobu działania modułu wstępnego ładowania obrazu, aby sprawdzić, czy obraz istnieje.

function checkImage(imageSrc, good, bad) {
    var img = new Image();
    img.onload = good; 
    img.onerror = bad;
    img.src = imageSrc;
}

checkImage("foo.gif", function(){ alert("good"); }, function(){ alert("bad"); } );

JSFiddle


Hej, fajna funkcja! Na marginesie, jest to interesujący sposób zwracania wyników bezpośrednio do funkcji anonimowej. Normalnie zrobiłbym to za pomocą returnstwierdzenia takiego jak @ajtrichards w pierwszej części jego odpowiedzi.
Sablefoste

Absolutnie; ale nigdy tak naprawdę nie myślałem o innym sposobie bycia synchronicznym. Pochodzę z długiej historii kodowania proceduralnego i czasami brakuje mi „innego” sposobu patrzenia na rzeczy… Założę się, że nie jestem jedyny. ;-)
Sablefoste

2
Jeśli przyszli pracownicy Google będą mieli problem z tym rozwiązaniem, spróbuj przenieść definicję img.src na bezpośrednio po nowej linii Image.
Gavin

52

Możesz po prostu sprawdzić, czy obraz się ładuje, czy nie, używając wbudowanych zdarzeń, które są dostarczane dla wszystkich obrazów.

onloadI onerrorwydarzenia powie, czy obraz załadowany pomyślnie lub jeśli wystąpił błąd:

var image = new Image();

image.onload = function() {
    // image exists and is loaded
    document.body.appendChild(image);
}
image.onerror = function() {
    // image did not load

    var err = new Image();
    err.src = '/error.png';

    document.body.appendChild(err);
}

image.src = "../imgs/6.jpg";

2
Najlepsza odpowiedź dla mnie, ponieważ działa w każdym przypadku (problem z połączeniem, zewnętrzny serwer ...) +1
Reign.85

2
Porównanie wydajności tej odpowiedzi z alternatywą AJAX.get. Ta odpowiedź działa znacznie szybciej!
Samuel

Podoba mi się to rozwiązanie, w każdym razie wprowadza zdarzenia w obu przypadkach (wykonanie asynchroniczne), które w niektórych sytuacjach mogą powodować problemy: w każdym przypadku sugerowałbym dołączenie obrazu, a następnie zastąpienie go tylko w przypadku błędów.
Giorgio Tempesta

@adeno, Czy to działa, gdy kod statusu: 404 Not Found
MahiMan

@Mahi - kod statusu nie powinien mieć znaczenia, o ile strona 404 w rzeczywistości nie zwróci prawidłowego obrazu, zakończy się niepowodzeniem i uruchomi errorprocedurę obsługi.
adeneo

15

Jeśli ktoś wejdzie na tę stronę i chce to zrobić w kliencie opartym na React , możesz zrobić coś takiego jak poniżej, która była oryginalną odpowiedzią dostarczoną przez Sophię Alpert z zespołu React tutaj

getInitialState: function(event) {
    return {image: "http://example.com/primary_image.jpg"};
},
handleError: function(event) {
    this.setState({image: "http://example.com/failover_image.jpg"});
},
render: function() {
    return (
        <img onError={this.handleError} src={src} />;
    );
}

7

Lepszym i nowoczesnym podejściem jest użycie ES6 Fetch API do sprawdzenia, czy obraz istnieje, czy nie:

fetch('https://via.placeholder.com/150', { method: 'HEAD' })
    .then(res => {
        if (res.ok) {
            console.log('Image exists.');
        } else {
            console.log('Image does not exist.');
        }
    }).catch(err => console.log('Error:', err));

Upewnij się, że wykonujesz żądania tego samego pochodzenia lub na serwerze jest włączony mechanizm CORS.


6

Jeśli utworzysz tag obrazu i dodasz go do DOM, powinno zostać uruchomione zdarzenie onload lub onerror. Jeśli wystąpi błąd onerror, obraz nie istnieje na serwerze.


3

Możesz wywołać tę funkcję JS, aby sprawdzić, czy plik istnieje na serwerze:

function doesFileExist(urlToFile)
{
    var xhr = new XMLHttpRequest();
    xhr.open('HEAD', urlToFile, false);
    xhr.send();

    if (xhr.status == "404") {
        console.log("File doesn't exist");
        return false;
    } else {
        console.log("File exists");
        return true;
    }
}

1
Dobry wysiłek. ale trochę czasochłonne przy ładowaniu wielu obrazów w jednym formularzu.
Nuwan Withanage

pokazuje błąd w xhr.send (), jeśli adres URL nie istnieje.
Avinash Sharma,

3

Basicaly promisified wersja @espascarello i @adeneo odpowiedzi, z parametrem awaryjnej:

const getImageOrFallback = (path, fallback) => {
  return new Promise(resolve => {
    const img = new Image();
    img.src = path;
    img.onload = () => resolve(path);
    img.onerror = () => resolve(fallback);
  });
};

// Usage:

const link = getImageOrFallback(
  'https://www.fillmurray.com/640/360',
  'https://via.placeholder.com/150'
  ).then(result => console.log(result) || result)

// It can be also implemented using the async / await API.

Uwaga: rozwiązanie może mi się fetchbardziej podobać , ale ma wadę - jeśli Twój serwer jest skonfigurowany w określony sposób, może zwrócić 200/304, nawet jeśli Twój plik nie istnieje. To z drugiej strony wystarczy.


2
Dla fetch, można użyć okwłasność responseobiektu, aby sprawdzić, czy wniosek był udany czy nie: fetch(url).then(res => {if(res.ok){ /*exist*/} else {/*not exist*/}});
attacomsian

To niestety nie działa, jeśli chcę sprawdzić prawidłowy obraz tła. background-image: url('/a/broken/url')daje mi 200i ok(Chrome 74).
HynekS

2

Możesz to zrobić za pomocą swoich axiosów, ustawiając względną ścieżkę do odpowiedniego folderu obrazów. Zrobiłem to, aby uzyskać plik JSON. Możesz wypróbować tę samą metodę dla pliku obrazu, możesz odnieść się do tych przykładów

Jeśli ustawiłeś już instancję axios z baseurl jako serwer w innej domenie, będziesz musiał użyć pełnej ścieżki do statycznego serwera plików, na którym wdrażasz aplikację internetową.

  axios.get('http://localhost:3000/assets/samplepic.png').then((response) => {
            console.log(response)
        }).catch((error) => {
            console.log(error)
        })

Jeśli obraz zostanie znaleziony, odpowiedź będzie wynosić 200, a jeśli nie, będzie to 404.

Ponadto, jeśli plik obrazu znajduje się w folderze zasobów wewnątrz src, możesz wykonać wymaganie, pobrać ścieżkę i wykonać powyższe wywołanie z tą ścieżką.

var SampleImagePath = require('./assets/samplepic.png');
axios.get(SampleImagePath).then(...)

0

To działa dobrze:

function checkImage(imageSrc) {
    var img = new Image();        
    try {
        img.src = imageSrc;
        return true;
    } catch(err) {
        return false;
    }    
}

12
Jesteś pewien, że to prawda za każdym razem?
Brandon McAlees

-3

Możesz odesłać ten link, aby sprawdzić, czy istnieje plik obrazu z JavaScript.

checkImageExist.js:

    var image = new Image();
    var url_image = './ImageFolder/' + variable + '.jpg';
    image.src = url_image;
    if (image.width == 0) {
       return `<img src='./ImageFolder/defaultImage.jpg'>`;
    } else {
       return `<img src='./ImageFolder/`+variable+`.jpg'`;
    } } ```

1
Właśnie to przetestowałem. To nie działa . Zawsze zwraca domyślny obraz. (Prawdopodobnie dlatego, że przeglądarka nie ma czasu na wysłanie żądania HTTP i załadowanie obrazu przed próbą przetestowania jego szerokości).
Quentin
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.