¿Verifica si la imagen existe en el servidor usando JavaScript?

124

Usando javascript, ¿hay alguna manera de saber si un recurso está disponible en el servidor? Por ejemplo, tengo imágenes 1.jpg - 5.jpg cargadas en la página html. Me gustaría llamar a una función de JavaScript cada minuto más o menos, que haría aproximadamente el siguiente código de borrador ...

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

Pensamientos? ¡Gracias!

0xhughes
fuente

Respuestas:

208

Podrías usar algo como:

function imageExists(image_url){

    var http = new XMLHttpRequest();

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

    return http.status != 404;

}

Obviamente, podría usar jQuery / similar para realizar su solicitud HTTP.

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

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

    })
ajtrichards
fuente
44
Pero el nombre de la función no debe ser fileExists porque funciona en .js .css .html o en cualquier otro archivo disponible públicamente.
CDR
1
La función es asombrosa. Lo puse en mi colección :) Pensé fileExistsque sería mejor nombre porque esta función no comprueba si la imagen existe en el servidor. Verifica si el archivo es accesible desde el servidor. No hay verificación si ese archivo es realmente una imagen. Podría ser .pdf, .html, algún archivo aleatorio renombrado a * .jpg o * .png. Si algo termina con .jpg no significa que sea 100% imagen :)
CDR
9
Esto fallará a menos que el acceso al recurso esté permitido según las reglas de CORS. Usar un Imageobjeto no sufre esa limitación. La única ventaja de esto es que en realidad no descargará la imagen.
Alnitak
8
problema de dominio cruzado.
Amit Kumar el
2
Esto funciona, pero tenga en cuenta que lleva más tiempo procesar la solicitud y no es la mejor solución. Además, no funciona en origen cruzado (definitivamente en Chrome), por lo que no puede usarlo en el archivo: /// protocolo, lo que significa que no hay uso local.
Cameron
118

Puede usar la forma básica en que funcionan los precargadores de imágenes para probar si existe una imagen.

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
fuente
¡Hola, buena función! Como nota al margen, esta es una forma interesante de devolver los resultados, directamente a una función anónima. Normalmente haría esto con una returndeclaración como @ajtrichards tiene en la primera parte de su respuesta.
Sablefoste
Absolutamente; pero en realidad nunca pensé que la otra forma fuera sincrónica. Vengo de una larga historia de codificación de procedimientos, y a veces echo de menos la "otra" forma de ver las cosas ... Apuesto a que no soy el único. ;-)
Sablefoste
2
Para futuros googlers que tengan un problema con esta solución, intente mover la definición img.src inmediatamente después de la nueva línea de imagen.
Gavin
52

Puede verificar si la imagen se carga o no utilizando los eventos integrados que se proporcionan para todas las imágenes.

Los eventos onloady onerrorle indicarán si la imagen se cargó correctamente o si ocurrió un error:

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
fuente
2
La mejor respuesta para mí, ya que funciona en todos los casos (problema de conexión, servidor externo ...) +1
Reign.85
2
Comparó el rendimiento de esta respuesta con la alternativa AJAX.get. ¡Esta respuesta funciona mucho más rápido!
Samuel
Me gusta esta solución, de todos modos introduce eventos en ambos casos (ejecución asíncrona), lo que puede causar problemas en algunas situaciones: sugeriría agregar la imagen en cualquier caso y luego sustituirla solo en caso de errores.
Giorgio Tempesta
@adeno, ¿funciona cuando Código de estado: 404 no encontrado
ManZ
@Mahi: el código de estado no debería importar, siempre que la página 404 no devuelva una imagen válida, fallará y activará el errorcontrolador.
Adeneo
15

Si alguien viene a esta página buscando hacer esto en un cliente basado en React , puede hacer algo como lo siguiente, que fue una respuesta original proporcionada por Sophia Alpert del equipo React aquí

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
fuente
7

Un enfoque mejor y moderno es usar ES6 Fetch API para verificar si una imagen existe o no:

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

Asegúrese de realizar las solicitudes del mismo origen o CORS está habilitado en el servidor.

atacomsian
fuente
6

Si crea una etiqueta de imagen y la agrega al DOM, su evento onload u onerror debería activarse. Si se activa un error, la imagen no existe en el servidor.

Douglas
fuente
3

Puede llamar a esta función JS para verificar si el archivo existe en el Servidor:

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
fuente
1
Buen esfuerzo. pero consume poco tiempo cuando se cargan varias imágenes en una sola forma.
Nuwan Withanage
muestra un error en xhr.send () si la url no existe.
Avinash Sharma
3

Básicamente, una versión promisificada de @espascarello y @adeneo responde, con un parámetro alternativo:

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.

Nota: Personalmente, me puede gustar más la fetchsolución, pero tiene un inconveniente: si su servidor está configurado de una manera específica, puede devolver 200/304, incluso si su archivo no existe. Esto, por otro lado, hará el trabajo.

HynekS
fuente
2
Para fetch, puede usar la okpropiedad del responseobjeto para verificar si la solicitud fue exitosa o no: fetch(url).then(res => {if(res.ok){ /*exist*/} else {/*not exist*/}});
attacomsian
Desafortunadamente, eso no funciona para mí si quiero verificar una imagen de fondo válida. background-image: url('/a/broken/url')me da 200y ok(Chrome 74).
HynekS
2

Puede hacer esto con sus axios configurando la ruta relativa a la carpeta de imágenes correspondiente. He hecho esto para obtener un archivo json. Puede probar el mismo método para un archivo de imagen, puede consultar estos ejemplos

Si ya ha configurado una instancia de axios con baseurl como servidor en un dominio diferente, tendrá que usar la ruta completa del servidor de archivos estático donde implementa la aplicación web.

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

Si se encuentra la imagen, la respuesta será 200 y, de lo contrario, será 404.

Además, si el archivo de imagen está presente en la carpeta de activos dentro de src, puede hacer un requerimiento, obtener la ruta y hacer la llamada anterior con esa ruta.

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

Esto funciona bien:

function checkImage(imageSrc) {
    var img = new Image();        
    try {
        img.src = imageSrc;
        return true;
    } catch(err) {
        return false;
    }    
}
Matkins
fuente
12
¿Estás seguro de que esto vuelve a ser cierto cada vez?
Brandon McAlees
-3

Puede consultar este enlace para verificar si existe un archivo de imagen con 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
fuente
1
Acabo de probar esto. No funciona . Siempre devuelve la imagen predeterminada. (Probablemente porque no hay tiempo para que el navegador realice la solicitud HTTP y cargue la imagen antes de intentar probar el ancho de la misma).
Quentin