ตรวจสอบว่ามีภาพอยู่บนเซิร์ฟเวอร์โดยใช้ JavaScript หรือไม่


124

การใช้ javascript มีวิธีที่จะบอกได้ว่าทรัพยากรมีอยู่บนเซิร์ฟเวอร์หรือไม่? ตัวอย่างเช่นฉันมีรูปภาพ 1.jpg - 5.jpg โหลดลงในหน้า html ฉันต้องการเรียกใช้ฟังก์ชัน JavaScript ทุกๆนาทีหรือมากกว่านั้นโดยประมาณจะทำรหัสเริ่มต้นต่อไปนี้ ...

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

คิด? ขอบคุณ!

คำตอบ:


208

คุณสามารถใช้สิ่งต่างๆเช่น:

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.

    })

4
แต่ไม่ควรใช้ชื่อฟังก์ชันเป็น fileExists เนื่องจากใช้ได้กับ. js .css .html หรือไฟล์สาธารณะอื่น ๆ
CoR

1
ฟังก์ชั่นน่ากลัว ฉันใส่ไว้ในคอลเลกชันของฉัน :) ฉันคิดว่าfileExistsน่าจะเป็นชื่อที่ดีกว่าเพราะฟังก์ชั่นนี้ไม่ได้ตรวจสอบว่ามีภาพอยู่บนเซิร์ฟเวอร์หรือไม่ ตรวจสอบว่าไฟล์สามารถเข้าถึงได้จากเซิร์ฟเวอร์หรือไม่ ไม่มีการตรวจสอบว่าไฟล์นั้นเป็นรูปภาพจริงหรือไม่ อาจเป็นไฟล์. pdf, .html, ไฟล์สุ่มบางไฟล์เปลี่ยนชื่อเป็น * .jpg หรือ * .png ถ้ามีอะไรลงท้ายด้วย. jpg ก็ไม่ได้หมายความว่าเป็นรูปภาพ 100% :)
CoR

9
การดำเนินการนี้จะล้มเหลวเว้นแต่การเข้าถึงทรัพยากรจะได้รับอนุญาตภายใต้กฎ CORS การใช้Imageวัตถุไม่ประสบกับข้อ จำกัด ดังกล่าว ข้อดีเพียงอย่างเดียวคือมันจะไม่ดาวน์โหลดภาพจริงๆ
Alnitak

8
ปัญหาข้ามโดเมน
Amit Kumar

2
วิธีนี้ได้ผล แต่โปรดทราบว่าการดำเนินการตามคำขอใช้เวลานานกว่าและไม่ใช่วิธีแก้ปัญหาที่ดีที่สุด นอกจากนี้ยังใช้ไม่ได้กับ cross origin (แน่นอนใน chrome) ดังนั้นคุณจึงไม่สามารถใช้กับโปรโตคอล file: /// ซึ่งหมายความว่าไม่มีการใช้งานในท้องถิ่น
Cameron

118

คุณสามารถใช้วิธีพื้นฐานในการทำงานของตัวโหลดรูปภาพล่วงหน้าเพื่อทดสอบว่ามีรูปภาพอยู่หรือไม่

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


เฮ้ฟังก์ชั่นเด็ด! ในฐานะที่เป็นบันทึกด้านข้างนี่เป็นวิธีที่น่าสนใจในการส่งคืนผลลัพธ์ตรงไปยังฟังก์ชันที่ไม่ระบุตัวตน โดยปกติฉันจะทำสิ่งนี้ด้วยreturnข้อความเช่น @ajtrichards ในส่วนแรกของคำตอบของเขา
Sablefoste

แน่นอน; แต่ฉันไม่เคยคิดถึงวิธีการซิงโครนัสแบบอื่นเลย ฉันมาจากประวัติศาสตร์อันยาวนานของการเข้ารหัสขั้นตอนและบางครั้งก็พลาดวิธีการมอง "อื่น ๆ " ... ฉันจะพนันได้เลยว่าฉันไม่ใช่คนเดียว ;-)
Sablefoste

2
สำหรับ Googler ในอนาคตที่มีปัญหาในการแก้ปัญหานี้ให้ลองย้ายนิยาม 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";

2
คำตอบที่ดีที่สุดสำหรับฉันเนื่องจากใช้ได้ในทุกกรณี (ปัญหาการเชื่อมต่อเซิร์ฟเวอร์ภายนอก ... ) +1
รัชกาลที่ 85

2
เปรียบเทียบประสิทธิภาพของคำตอบนี้กับทางเลือก AJAX.get คำตอบนี้ทำงานได้เร็วขึ้นมาก!
ซามูเอล

ฉันชอบวิธีแก้ปัญหานี้อย่างไรก็ตามมันแนะนำเหตุการณ์ในทั้งสองกรณี (การดำเนินการแบบอะซิงโครนัส) ซึ่งอาจทำให้เกิดปัญหาในบางสถานการณ์: ฉันขอแนะนำให้ต่อท้ายรูปภาพไม่ว่าในกรณีใด ๆ แล้วแทนที่ในกรณีที่มีข้อผิดพลาดเท่านั้น
Giorgio Tempesta

@adeno ใช้งานได้เมื่อรหัสสถานะ: 404 ไม่พบ
MahiMan

@Mahi - รหัสสถานะไม่ควรมีความสำคัญตราบใดที่หน้า 404 ไม่ส่งคืนรูปภาพที่ถูกต้องมันจะล้มเหลวและเรียกerrorตัวจัดการ
adeneo

15

หากใครมาที่หน้านี้เพื่อต้องการทำสิ่งนี้ในไคลเอนต์Reactคุณสามารถทำสิ่งต่างๆดังต่อไปนี้ซึ่งเป็นคำตอบต้นฉบับที่จัดทำโดย Sophia Alpert จากทีม 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 บนเซิร์ฟเวอร์


6

หากคุณสร้างแท็กรูปภาพและเพิ่มลงใน DOM เหตุการณ์ onload หรือ 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
ความพยายามที่ดี แต่เสียเวลาเล็กน้อยเมื่อโหลดหลายภาพในรูปแบบเดียว
หนูวรรณวิธาน

มันแสดงข้อผิดพลาดที่ xhr.send () หากไม่มี url
Avinash Sharma

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 ได้แม้ว่าไฟล์ของคุณจะไม่มีอยู่ก็ตาม ในทางกลับกันสิ่งนี้จะได้ผล


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

คุณสามารถทำได้ด้วยแกนของคุณโดยตั้งค่าพา ธ สัมพัทธ์ไปยังโฟลเดอร์รูปภาพที่เกี่ยวข้อง ฉันได้ทำสิ่งนี้เพื่อรับไฟล์ json คุณสามารถลองใช้วิธีการเดียวกันกับไฟล์รูปภาพโดยอ้างอิงจากตัวอย่างเหล่านี้

หากคุณตั้งค่าอินสแตนซ์ axios ที่มี baseurl เป็นเซิร์ฟเวอร์ในโดเมนอื่นแล้วคุณจะต้องใช้เส้นทางแบบเต็มของไฟล์เซิร์ฟเวอร์แบบคงที่ที่คุณปรับใช้เว็บแอปพลิเคชัน

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

หากพบภาพการตอบสนองจะเป็น 200 และหากไม่เป็นเช่นนั้นจะเป็น 404

นอกจากนี้หากไฟล์รูปภาพอยู่ในโฟลเดอร์ assets ภายใน 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;
    }    
}

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 และโหลดภาพก่อนที่คุณจะลองทดสอบความกว้างของมัน)
Quentin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.