Проверить, существует ли изображение на сервере с помощью JavaScript?

124

Есть ли способ узнать, доступен ли ресурс на сервере с помощью javascript? Например, у меня есть изображения 1.jpg - 5.jpg, загруженные на страницу html. Я хотел бы каждую минуту вызывать функцию JavaScript, которая примерно выполняла бы следующий рабочий код ...

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

Мысли? Спасибо!

0xhughes
источник

Ответы:

209

Вы можете использовать что-то вроде:

function imageExists(image_url){

    var http = new XMLHttpRequest();

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

    return http.status != 404;

}

Очевидно, вы можете использовать jQuery / similar для выполнения вашего HTTP-запроса.

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

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

    })
ajtrichards
источник
4
Но имя функции не должно быть fileExists, потому что это работает с .js .css .html или любым другим общедоступным файлом.
CoR
1
Функция потрясающая. Я положил его в свою коллекцию :) Я подумал, fileExistsчто будет лучше, потому что эта функция не проверяет, существует ли изображение на сервере. Он проверяет, доступен ли файл с сервера. Нет проверки, действительно ли этот файл является изображением. Это может быть .pdf, .html, какой-нибудь случайный файл, переименованный в * .jpg или * .png. Если что-то заканчивается на .jpg, это не значит, что это 100% изображение :)
CoR
9
Это не удастся, если доступ к ресурсу не разрешен правилами CORS. Использование Imageобъекта не страдает этим ограничением. Единственное преимущество этого заключается в том, что на самом деле он не загружает изображение.
Alnitak
8
междоменная проблема.
Амит Кумар,
2
Это работает, но имейте в виду, что обработка запроса занимает больше времени и не является лучшим решением. Также он не работает с перекрестным происхождением (определенно в хроме), поэтому вы не можете использовать его по протоколу file: ///, что означает отсутствие локального использования.
Кэмерон
119

Вы можете использовать основной способ работы предварительных загрузчиков изображений, чтобы проверить, существует ли изображение.

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
источник
Эй, классная функция! Кстати, это интересный способ возврата результатов прямо в анонимную функцию. Обычно я бы сделал это с таким returnутверждением, как @ajtrichards в первой части его ответа.
Sablefoste
Абсолютно; но я никогда особо не думал о другом способе синхронности. Я исхожу из долгой истории процедурного кодирования и иногда скучаю по «другому» взгляду на вещи ... Готов поспорить, я не единственный. ;-)
Sablefoste
2
Если у будущих гуглеров возникнут проблемы с этим решением, попробуйте переместить определение img.src сразу после новой строки изображения.
Gavin
52

Вы можете просто проверить, загружается ли изображение или нет, используя встроенные события, которые предусмотрены для всех изображений.

События onloadи onerrorсообщат вам, успешно ли загружено изображение или произошла ошибка:

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
источник
2
Лучший ответ для меня, так как он работает во всех случаях (проблема с
подключением
2
Сравнил производительность этого ответа с альтернативой AJAX.get. Этот ответ выполняется намного быстрее!
Samuel
Мне нравится это решение, так или иначе, оно вводит события в обоих случаях (асинхронное выполнение), что может вызвать проблемы в некоторых ситуациях: я бы предложил добавить изображение в любом случае, а затем заменить его только в случае ошибок.
Джорджио Темпеста
@adeno, это работает, когда код состояния: 404 не найден
MahiMan
@Mahi - код состояния не имеет значения, пока страница 404 не возвращает действительное изображение, она завершится ошибкой и вызовет errorобработчик.
adeneo
15

Если кто-то заходит на эту страницу, чтобы сделать это в клиенте на основе React , вы можете сделать что-то вроде приведенного ниже, оригинального ответа, предоставленного Софией Альперт из команды React здесь

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

Более эффективный и современный подход - использовать ES6 Fetch API, чтобы проверить, существует ли изображение или нет:

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

Убедитесь, что вы либо делаете запросы с одинаковым источником, либо на сервере включен CORS.

attacomsian
источник
6

Если вы создаете тег изображения и добавляете его в DOM, должно срабатывать событие onload или onerror. Если возникает ошибка onerror, изображение не существует на сервере.

Дуглас
источник
3

Вы можете вызвать эту функцию JS, чтобы проверить, существует ли файл на сервере:

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
Хорошее усилие. но требует немного времени при загрузке нескольких изображений в одной форме.
Nuwan Withanage
он показывает ошибку в xhr.send (), если URL-адрес не существует.
Авинаш Шарма
3

В основном это обещанная версия ответов @espascarello и @adeneo с резервным параметром:

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.

Примечание. Мне лично может понравиться fetchрешение больше, но у него есть недостаток - если ваш сервер настроен определенным образом, он может возвращать 200/304, даже если ваш файл не существует. Это, с другой стороны, сработает.

HynekS
источник
2
В fetchсамом деле, вы можете использовать okсвойство responseобъекта, чтобы проверить, был ли запрос успешным или нет: fetch(url).then(res => {if(res.ok){ /*exist*/} else {/*not exist*/}});
attacomsian
К сожалению, это не работает для меня, если я хочу проверить действительное фоновое изображение. background-image: url('/a/broken/url')дает мне 200и ok(Chrome 74).
HynekS
2

Вы можете сделать это с помощью своих axios, установив относительный путь к соответствующей папке изображений. Я сделал это для получения файла json. Вы можете попробовать тот же метод для файла изображения, вы можете сослаться на эти примеры

Если вы уже установили экземпляр axios с baseurl в качестве сервера в другом домене, вам придется использовать полный путь к статическому файловому серверу, на котором вы развертываете веб-приложение.

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

Если изображение найдено, ответ будет 200, а если нет - 404.

Кроме того, если файл изображения присутствует в папке с ресурсами внутри src, вы можете выполнить требование, получить путь и выполнить вышеуказанный вызов с этим путем.

var SampleImagePath = require('./assets/samplepic.png');
axios.get(SampleImagePath).then(...)
Рохит Мурали
источник
0

Это отлично работает:

function checkImage(imageSrc) {
    var img = new Image();        
    try {
        img.src = imageSrc;
        return true;
    } catch(err) {
        return false;
    }    
}
MAtkins
источник
12
Уверены, что это каждый раз возвращает истину?
Brandon McAlees
-3

Вы можете обратиться по этой ссылке, чтобы проверить, существует ли файл изображения с помощью 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
Я только что это проверил. Не работает . Он всегда возвращает изображение по умолчанию. (Вероятно, потому что браузеру некогда сделать HTTP-запрос и загрузить изображение, прежде чем вы попытаетесь проверить его ширину).
Квентин