Kiểm tra xem hình ảnh có tồn tại trên máy chủ bằng JavaScript không?


124

Sử dụng javascript có cách nào để biết tài nguyên có sẵn trên máy chủ không? Ví dụ, tôi có hình ảnh 1.jpg - 5.jpg được tải vào trang html. Tôi muốn gọi một hàm JavaScript mỗi phút hoặc lâu hơn, điều đó gần như sẽ thực hiện mã cào sau ...

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

Suy nghĩ? Cảm ơn!

Câu trả lời:


208

Bạn có thể sử dụng một cái gì đó như:

function imageExists(image_url){

    var http = new XMLHttpRequest();

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

    return http.status != 404;

}

Rõ ràng là bạn có thể sử dụng jQuery / tương tự để thực hiện yêu cầu HTTP của mình.

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

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

    })

4
Nhưng không nên đặt tên hàm là fileExists vì nó hoạt động trên .js .css .html hoặc bất kỳ tệp công khai nào khác.
CoR

1
Chức năng là tuyệt vời. Tôi đã đưa nó vào bộ sưu tập của mình :) Tôi nghĩ fileExistssẽ là cái tên tốt hơn vì chức năng này không kiểm tra xem hình ảnh có tồn tại trên máy chủ hay không. Nó kiểm tra xem tệp có thể truy cập được từ máy chủ hay không. Không có kiểm tra nếu tệp đó thực sự là một hình ảnh. Nó có thể là .pdf, .html, một số tệp ngẫu nhiên được đổi tên thành * .jpg hoặc * .png. Nếu thứ gì đó kết thúc bằng .jpg thì điều đó không có nghĩa là đó là hình ảnh 100% :)
CoR

9
Điều này sẽ không thành công trừ khi được phép truy cập tài nguyên theo quy tắc CORS. Sử dụng một Imageđối tượng không bị giới hạn đó. Ưu điểm duy nhất của điều này là nó sẽ không thực sự tải xuống hình ảnh.
Alnitak

8
vấn đề tên miền chéo.
Amit Kumar,

2
Điều này có hiệu quả, nhưng hãy nhớ rằng mất nhiều thời gian hơn để xử lý yêu cầu và không phải là giải pháp tốt nhất. Ngoài ra, nó không hoạt động trên nguồn gốc chéo (chắc chắn là trong chrome) nên bạn không thể sử dụng nó trên giao thức tệp: /// có nghĩa là không sử dụng cục bộ.
Cameron

118

Bạn có thể sử dụng cách cơ bản của trình tải trước hình ảnh hoạt động để kiểm tra xem hình ảnh có tồn tại hay không.

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


Này, chức năng tuyệt vời! Lưu ý thêm, đây là một cách thú vị để trả về kết quả, chuyển trực tiếp vào một hàm ẩn danh. Tôi thường làm điều này với một returntuyên bố như @ajtrichards có trong phần đầu tiên của câu trả lời của anh ấy.
Sablefoste

Chắc chắn rồi; nhưng tôi chưa bao giờ thực sự nghĩ về cách khác là đồng bộ. Tôi đến từ một lịch sử lâu đời về mã hóa thủ tục, và đôi khi bỏ lỡ cách nhìn nhận "khác" ... Tôi cá rằng tôi không phải là người duy nhất. ;-)
Sablefoste

2
Đối với các nhân viên google tương lai gặp sự cố, giải pháp này, hãy thử di chuyển định nghĩa img.src sang ngay sau dòng Hình ảnh mới.
Gavin

52

Bạn chỉ có thể kiểm tra xem hình ảnh có tải hay không bằng cách sử dụng các sự kiện tích hợp được cung cấp cho tất cả các hình ảnh.

Các sự kiện onloadonerrorsẽ cho bạn biết nếu hình ảnh được tải thành công hoặc nếu xảy ra lỗi:

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
Câu trả lời tốt nhất cho tôi, vì nó hoạt động trong mọi trường hợp (sự cố kết nối, máy chủ bên ngoài ...) +1
Reign. 85

2
So sánh hiệu suất của câu trả lời này với giải pháp thay thế AJAX.get. Câu trả lời này thực hiện nhanh hơn nhiều!
Samuel

Tôi thích giải pháp này, dù sao nó cũng giới thiệu các sự kiện trong cả hai trường hợp (thực thi không đồng bộ), có thể gây ra sự cố trong một số trường hợp: Tôi khuyên bạn nên nối hình ảnh trong mọi trường hợp và sau đó chỉ thay thế nó trong trường hợp có lỗi.
Giorgio Tempesta

@adeno, Nó có hoạt động không khi Mã trạng thái: 404 Không tìm thấy
MahiMan

@Mahi - Mã trạng thái không quan trọng, miễn là trang 404 không thực sự trả lại hình ảnh hợp lệ, nó sẽ bị lỗi và kích hoạt errortrình xử lý.
adeneo

15

Nếu bất kỳ ai truy cập trang này muốn thực hiện việc này trong một ứng dụng khách dựa trên React , bạn có thể làm như sau, đây là câu trả lời ban đầu được cung cấp bởi Sophia Alpert của nhóm React tại đây

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

Một cách tiếp cận hiện đại và tốt hơn là sử dụng API Tìm nạp ES6 để kiểm tra xem hình ảnh có tồn tại hay không:

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

Đảm bảo rằng bạn đang thực hiện các yêu cầu có cùng nguồn gốc hoặc CORS được bật trên máy chủ.


6

Nếu bạn tạo một thẻ hình ảnh và thêm nó vào DOM, thì sự kiện onload hoặc onerror của nó sẽ kích hoạt. Nếu lỗi kích hoạt, hình ảnh không tồn tại trên máy chủ.


3

Bạn có thể gọi hàm JS này để kiểm tra xem tệp có tồn tại trên Máy chủ hay không:

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
Nỗ lực tốt. nhưng hơi tốn thời gian khi tải nhiều hình ảnh ở một dạng duy nhất.
Nuwan Withanage

nó hiển thị lỗi tại xhr.send () nếu url không tồn tại.
Avinash Sharma

3

Về cơ bản một promisified phiên bản của @espascarello và câu trả lời @adeneo, với một tham số dự phòng:

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.

Lưu ý: Cá nhân tôi có thể thích fetchgiải pháp này hơn, nhưng nó có một nhược điểm - nếu máy chủ của bạn được định cấu hình theo một cách cụ thể, nó có thể trả về 200/304, ngay cả khi tệp của bạn không tồn tại. Điều này, mặt khác, sẽ thực hiện công việc.


2
Đối với fetch, bạn có thể sử dụng thuộc oktính của responseđối tượng để kiểm tra xem yêu cầu có thành công hay không: fetch(url).then(res => {if(res.ok){ /*exist*/} else {/*not exist*/}});
attacomsian

Rất tiếc, điều đó không hoạt động đối với tôi nếu tôi muốn kiểm tra hình nền hợp lệ. background-image: url('/a/broken/url')cho tôi 200ok(Chrome 74).
HynekS

2

Bạn có thể làm điều này với axios của mình bằng cách đặt đường dẫn tương đối đến thư mục hình ảnh tương ứng. Tôi đã làm điều này để nhận được một tệp json. Bạn có thể thử phương pháp tương tự cho tệp hình ảnh, bạn có thể tham khảo các ví dụ sau

Nếu bạn đã đặt một phiên bản axios với baseurl làm máy chủ trong miền khác, bạn sẽ phải sử dụng đường dẫn đầy đủ của máy chủ tệp tĩnh nơi bạn triển khai ứng dụng web.

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

Nếu hình ảnh được tìm thấy, phản hồi sẽ là 200 và nếu không, nó sẽ là 404.

Ngoài ra, nếu tệp hình ảnh có trong thư mục nội dung bên trong src, bạn có thể thực hiện yêu cầu, lấy đường dẫn và thực hiện lệnh gọi ở trên với đường dẫn đó.

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

0

Điều này hoạt động tốt:

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

12
Khá chắc chắn điều này trở lại đúng mọi lúc?
Brandon McAlees

-3

Bạn có thể tham khảo liên kết này để kiểm tra xem tệp hình ảnh có tồn tại bằng JavaScript hay không.

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
Tôi vừa thử nghiệm cái này. Nó không hoạt động . Nó luôn trả về hình ảnh mặc định. (Có thể là do không có thời gian để trình duyệt thực hiện yêu cầu HTTP và tải hình ảnh trước khi bạn thử kiểm tra chiều rộng của nó).
Quentin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.