Verifique se a imagem existe no servidor usando JavaScript?

124

Usando javascript, há uma maneira de saber se um recurso está disponível no servidor? Por exemplo, tenho imagens 1.jpg - 5.jpg carregadas na página html. Gostaria de chamar uma função JavaScript a cada minuto ou mais, que faria aproximadamente o seguinte código de rascunho ...

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

Pensamentos? Obrigado!

0xhughes
fonte

Respostas:

208

Você pode usar algo como:

function imageExists(image_url){

    var http = new XMLHttpRequest();

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

    return http.status != 404;

}

Obviamente, você pode usar o jQuery / similar para executar sua solicitação HTTP.

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

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

    })
ajtrichards
fonte
4
Mas o nome da função não deve ser fileExists, pois funciona em .js .css .html ou em qualquer outro arquivo disponível publicamente.
CR
1
Função é incrível. Coloquei-o na minha coleção :) Pensei fileExistsque seria um nome melhor, porque essa função não verifica se a imagem existe no servidor. Ele verifica se o arquivo está acessível no servidor. Não há como verificar se esse arquivo é realmente uma imagem. Pode ser .pdf, .html, algum arquivo aleatório renomeado para * .jpg ou * .png. Se extremidades algo com .jpg isso não significa que ele é 100% imagem :)
CR
9
Isso falhará, a menos que o acesso ao recurso seja permitido pelas regras do CORS. O uso de um Imageobjeto não sofre essa limitação. A única vantagem disso é que ele não fará o download da imagem.
Alnitak
8
problema entre domínios.
Amit Kumar
2
Isso funciona, mas lembre-se de que leva mais tempo para processar a solicitação e não é a melhor solução. Além disso, ele não funciona na origem cruzada (definitivamente no chrome), então você não pode usá-lo no arquivo: /// protocol, o que significa que não há uso local.
Cameron
118

Você pode usar o modo básico como os pré-carregadores de imagens funcionam para testar se existe uma imagem.

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
fonte
Ei, função legal! Como uma observação lateral, esta é uma maneira interessante de retornar os resultados, diretamente em uma função anônima. Normalmente, eu faria isso com uma returndeclaração como @ajtrichards na primeira parte de sua resposta.
precisa saber é o seguinte
Absolutamente; mas nunca pensei realmente na outra maneira de ser síncrona. Eu venho de uma longa história de codificação processual e, às vezes, sinto falta da "outra" maneira de ver as coisas ... aposto que não sou a única. ;-)
Sablefoste
2
Para futuros googlers com problemas nessa solução, tente mover a definição img.src para imediatamente após a nova linha de imagem.
Gavin
52

Você pode apenas verificar se a imagem carrega ou não, usando os eventos internos fornecidos para todas as imagens.

Os eventos onloade onerrorinformarão se a imagem foi carregada com sucesso ou se ocorreu um erro:

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
fonte
2
A melhor resposta para mim, como ele funciona em todos os casos (problema de conexão, servidor externo ...) +1
Reign.85
2
Comparou o desempenho desta resposta com a alternativa AJAX.get. Esta resposta executa muito mais rápido!
Samuel
Eu gosto dessa solução, de qualquer forma, ela introduz eventos nos dois casos (execução assíncrona), o que pode causar problemas em algumas situações: sugiro acrescentar a imagem em qualquer caso e substituí-la apenas no caso de erros.
Giorgio Tempesta 31/01
@adeno, Funciona quando Código de Status: 404 Não Encontrado
ManZ 11/19/19
@ Mahi - O código de status não deve importar, desde que a página 404 não retorne uma imagem válida, ela falhará e acionará o errormanipulador.
21419 adeneo
15

Se alguém chegar a esta página procurando fazer isso em um cliente baseado no React , você pode fazer algo como o abaixo, que foi uma resposta original fornecida por Sophia Alpert da equipe do React aqui

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

Uma abordagem melhor e moderna é usar a API de busca do ES6 para verificar se uma imagem existe ou não:

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

Verifique se você está fazendo as solicitações da mesma origem ou se o CORS está ativado no servidor.

attacomsian
fonte
6

Se você criar uma tag de imagem e adicioná-la ao DOM, seu evento onload ou onerror deverá ser acionado. Se um erro for disparado, a imagem não existe no servidor.

Douglas
fonte
3

Você pode chamar essa função JS para verificar se o arquivo existe no 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
fonte
1
Bom esforço. mas um pouco demorado ao carregar várias imagens em formato único.
Nuwan Withanage
mostra erro em xhr.send () se o URL não existir.
Avinash Sharma
3

Basicamente um promisified versão do @espascarello e respostas @adeneo, com um parâmetro de fallback:

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: Eu pessoalmente gosto mais da fetchsolução, mas ela tem uma desvantagem - se o servidor estiver configurado de uma maneira específica, ele poderá retornar 200/304, mesmo que o arquivo não exista. Por outro lado, isso fará o trabalho.

HynekS
fonte
2
Para fetch, você pode usar a okpropriedade do responseobjeto para verificar se a solicitação foi bem-sucedida ou não: fetch(url).then(res => {if(res.ok){ /*exist*/} else {/*not exist*/}});
attacomsian
Infelizmente, isso não funciona para mim se eu quiser verificar uma imagem de plano de fundo válida. background-image: url('/a/broken/url')me dá 200e ok(Chrome 74).
HynekS
2

Você pode fazer isso com seus axios definindo o caminho relativo para a pasta de imagens correspondente. Eu fiz isso para obter um arquivo json. Você pode tentar o mesmo método para um arquivo de imagem, pode consultar estes exemplos

Se você já definiu uma instância do axios com baseurl como um servidor em um domínio diferente, precisará usar o caminho completo do servidor de arquivos estático no qual implementa o aplicativo Web.

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

Se a imagem for encontrada, a resposta será 200 e, se não, será 404.

Além disso, se o arquivo de imagem estiver presente na pasta assets dentro do src, você poderá solicitar, obter o caminho e fazer a chamada acima com esse caminho.

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

Isso funciona bem:

function checkImage(imageSrc) {
    var img = new Image();        
    try {
        img.src = imageSrc;
        return true;
    } catch(err) {
        return false;
    }    
}
MAtkins
fonte
12
Certeza de que isso retorna sempre verdade?
Brandon McAlees
-3

Você pode consultar este link para verificar se existe um arquivo de imagem com 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
fonte
1
Acabei de testar isso. Isso não funciona . Sempre retorna a imagem padrão. (Provavelmente porque não há tempo para o navegador fazer a solicitação HTTP e carregar a imagem antes de tentar testar sua largura).
Quentin