Vérifier si l'image existe sur le serveur en utilisant JavaScript?

124

Utiliser javascript est-il possible de savoir si une ressource est disponible sur le serveur? Par exemple, j'ai des images 1.jpg - 5.jpg chargées dans la page html. Je voudrais appeler une fonction JavaScript toutes les minutes environ qui ferait à peu près le code de travail suivant ...

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

Pensées? Merci!

0xhughes
la source

Réponses:

208

Vous pouvez utiliser quelque chose comme:

function imageExists(image_url){

    var http = new XMLHttpRequest();

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

    return http.status != 404;

}

Évidemment, vous pouvez utiliser jQuery / similar pour effectuer votre requête HTTP.

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

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

    })
ajtrichards
la source
4
Mais le nom de la fonction ne devrait pas être fileExists car cela fonctionne sur .js .css .html ou tout autre fichier accessible au public.
CdR du
1
La fonction est géniale. Je l'ai mis dans ma collection :) Je pensais que ce fileExistsserait un meilleur nom car cette fonction ne vérifie pas si l'image existe sur le serveur. Il vérifie si le fichier est accessible depuis le serveur. Il n'y a pas de vérification si ce fichier est réellement une image. Cela peut être .pdf, .html, un fichier aléatoire renommé en * .jpg ou * .png. Si quelque chose se termine par .jpg, cela ne veut pas dire que c'est 100% image :)
CoR
9
Cela échouera à moins que l'accès à la ressource ne soit autorisé selon les règles CORS. L'utilisation d'un Imageobjet ne souffre pas de cette limitation. Le seul avantage de ceci est qu'il ne téléchargera pas réellement l'image.
Alnitak
8
problème interdomaine.
Amit Kumar
2
Cela fonctionne, mais gardez à l'esprit que le traitement de la demande prend plus de temps et n'est pas la meilleure solution. De plus, cela ne fonctionne pas sur l'origine croisée (certainement dans Chrome), vous ne pouvez donc pas l'utiliser sur le protocole file: ///, ce qui signifie aucune utilisation locale.
Cameron
118

Vous pouvez utiliser le fonctionnement de base des préchargeurs d'images pour tester si une image existe.

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

epascarello
la source
Hé, fonction cool! En passant, c'est une manière intéressante de renvoyer les résultats, directement dans une fonction anonyme. Je ferais normalement cela avec une returndéclaration comme @ajtrichards dans la première partie de sa réponse.
Sablefoste
Absolument; mais je n'ai jamais vraiment pensé que l'inverse était synchrone. Je viens d'une longue histoire de codage procédural, et je rate parfois «l'autre» façon de voir les choses ... Je parie que je ne suis pas la seule. ;-)
Sablefoste
2
Pour les futurs googleurs ayant un problème avec cette solution, essayez de déplacer la définition img.src immédiatement après la nouvelle ligne Image.
Gavin le
52

Vous pouvez simplement vérifier si l'image se charge ou non en utilisant les événements intégrés fournis pour toutes les images.

Les événements onloadet onerrorvous indiqueront si l'image a été chargée avec succès ou si une erreur s'est produite:

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";
adeneo
la source
2
La meilleure réponse pour moi, car cela fonctionne dans tous les cas (problème de connexion, serveur externe ...) +1
Reign.85
2
Comparé les performances de cette réponse avec l'alternative AJAX.get. Cette réponse est beaucoup plus rapide!
Samuel
J'aime cette solution, de toute façon elle introduit des événements dans les deux cas (exécution asynchrone), ce qui peut poser des problèmes dans certaines situations: je suggérerais de rajouter l'image dans tous les cas et de la remplacer uniquement en cas d'erreurs.
Giorgio Tempesta
@adeno, fonctionne-t-il lorsque le code d'état: 404 est introuvable
MahiMan
@Mahi - Le code d'état ne devrait pas avoir d'importance, tant que la page 404 ne renvoie pas réellement une image valide, elle échouera et déclenchera le errorgestionnaire.
adeneo
15

Si quelqu'un vient sur cette page pour le faire dans un client basé sur React , vous pouvez faire quelque chose comme ci-dessous, qui était une réponse originale fournie par Sophia Alpert de l'équipe React ici

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} />;
    );
}
Jordan Bonitatis
la source
7

Une approche meilleure et moderne consiste à utiliser l' API ES6 Fetch pour vérifier si une image existe ou non:

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

Assurez-vous que vous effectuez les demandes de même origine ou que CORS est activé sur le serveur.

attacomsien
la source
6

Si vous créez une balise d'image et l'ajoutez au DOM, son événement onload ou onerror devrait se déclencher. Si une erreur se déclenche, l'image n'existe pas sur le serveur.

Douglas
la source
3

Vous pouvez appeler cette fonction JS pour vérifier si le fichier existe sur le serveur:

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;
    }
}
Ani Menon
la source
1
Bon effort. mais peu de temps lors du chargement de plusieurs images sous une seule forme.
Nuwan Withanage
il affiche une erreur à xhr.send () si l'url n'existe pas.
Avinash Sharma le
3

Fondamentalement, une version promis de @espascarello et @adeneo répond, avec un paramètre de repli:

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.

Remarque: Personnellement, j'apprécie fetchdavantage la solution, mais elle présente un inconvénient: si votre serveur est configuré d'une manière spécifique, il peut renvoyer 200/304, même si votre fichier n'existe pas. Ceci, d'autre part, fera le travail.

HynekS
la source
2
Pour fetch, vous pouvez utiliser la okpropriété de l' responseobjet pour vérifier si la requête a réussi ou non: fetch(url).then(res => {if(res.ok){ /*exist*/} else {/*not exist*/}});
attacomsian
Cela ne fonctionne malheureusement pas pour moi si je veux vérifier une image de fond valide. background-image: url('/a/broken/url')me donne 200et ok(Chrome 74).
HynekS
2

Vous pouvez le faire avec votre axios en définissant un chemin relatif vers le dossier d'images correspondant. J'ai fait cela pour obtenir un fichier json. Vous pouvez essayer la même méthode pour un fichier image, vous pouvez vous référer à ces exemples

Si vous avez déjà défini une instance axios avec baseurl comme serveur dans un domaine différent, vous devrez utiliser le chemin complet du serveur de fichiers statiques sur lequel vous déployez l'application Web.

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

Si l'image est trouvée, la réponse sera 200 et sinon, elle sera 404.

De plus, si le fichier image est présent dans le dossier assets à l'intérieur de src, vous pouvez faire un require, obtenir le chemin et faire l'appel ci-dessus avec ce chemin.

var SampleImagePath = require('./assets/samplepic.png');
axios.get(SampleImagePath).then(...)
Rohith Murali
la source
0

Cela fonctionne bien:

function checkImage(imageSrc) {
    var img = new Image();        
    try {
        img.src = imageSrc;
        return true;
    } catch(err) {
        return false;
    }    
}
MAtkins
la source
12
Assez sûr que cela revient vrai à chaque fois?
Brandon McAlees
-3

Vous pouvez consulter ce lien pour vérifier si un fichier image existe avec 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'`;
    } } ```
Atik Vhora
la source
1
Je viens de tester ça. Ça ne marche pas . Il renvoie toujours l'image par défaut. (Probablement parce que le navigateur n'a pas le temps de faire la requête HTTP et de charger l'image avant d'essayer d'en tester la largeur).
Quentin