【问题标题】:Check if image exists on server using JavaScript?使用 JavaScript 检查图像是否存在于服务器上?
【发布时间】:2013-09-21 04:14:16
【问题描述】:

使用 javascript 有没有办法判断服务器上的资源是否可用?例如,我将图像 1.jpg - 5.jpg 加载到 html 页面中。我想每隔一分钟左右调用一个 JavaScript 函数,大致会执行以下临时代码...

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

想法?谢谢!

【问题讨论】:

    标签: javascript


    【解决方案1】:

    你可以使用类似的东西:

    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.
    
        })
    

    【讨论】:

    • 但函数名不应该是 fileExists,因为这适用于 .js .css .html 或任何其他公开可用的文件。
    • 功能很棒。我把它放在我的收藏中:) 我认为fileExists 会更好,因为这个函数不检查服务器上是否存在图像。它检查文件是否可以从服务器访问。没有检查该文件是否实际上是图像。它可能是 .pdf、.html、一些重命名为 *.jpg 或 *.png 的随机文件。如果某些东西以 .jpg 结尾,这并不意味着它是 100% 图像:)
    • 除非 CORS 规则允许访问资源,否则这将失败。使用 Image 对象不会受到这种限制。这样做的唯一好处是它不会真正下载图像。
    • 跨域问题。
    • 这确实有效,但请记住,处理请求需要更长的时间并且不是最佳解决方案。此外,它不适用于跨源(肯定在 chrome 中),因此您不能在 file:/// 协议上使用它,这意味着没有本地使用。
    【解决方案2】:

    您可以使用图像预加载器的基本工作方式来测试图像是否存在。

    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

    【讨论】:

    • 嘿,很酷的功能!作为旁注,这是一种将结果直接返回到匿名函数的有趣方式。我通常会使用@ajtrichards 在他的回答的第一部分中的return 声明来做到这一点。
    • 绝对的;但我从来没有真正考虑过同步的另一种方式。我来自程序编码的悠久历史,有时会错过看待事物的“其他”方式......我敢打赌我不是唯一的。 ;-)
    • 对于未来遇到此解决方案问题的谷歌用户,请尝试将 img.src 定义移动到新 Image 行之后。
    • 如果图像服务器返回带有实际图像内容的 404,这将无助于捕获 404 错误,例如Youtube 缩略图服务:i3.ytimg.com/vi/vGc4mg5pul4/maxresdefault.jpg
    • @gvlasov 因此,如果是这种情况,您必须执行头部请求并查看响应。 2013 年的一个问题中的一个选项......
    【解决方案3】:

    您可以使用为所有图像提供的内置事件来检查图像是否加载。

    onloadonerror 事件将告诉您图像是否加载成功或是否发生错误:

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

    【讨论】:

    • 对我来说最好的答案,因为它适用于任何情况(连接问题,外部服务器......)+1
    • 将此答案的性能与 AJAX.get 替代方案进行了比较。这个答案执行得更快!
    • 我喜欢这个解决方案,无论如何它在两种情况下都会引入事件(异步执行),这在某些情况下可能会导致问题:我建议在任何情况下都附加图像,然后仅在错误的情况。
    • @adeno,当状态码:404 Not Found 时是否有效
    • @Mahi - 状态码无关紧要,只要 404 页面实际上没有返回有效图像,它就会失败并触发 error 处理程序。
    【解决方案4】:

    更好的现代方法是使用 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。

    【讨论】:

    • 2020 年最简单的方法。谢谢。
    • 这太不可思议了。这是什么时候出现的?
    • @KyleBaker Fetch API 长期可用。它现在得到所有现代浏览器的广泛支持 - 几乎 95%。
    【解决方案5】:

    如果有人来到此页面希望在基于 React 的客户端中执行此操作,您可以执行以下操作,这是由 React 团队的 Sophia Alpert @987654321 提供的原始答案@

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

    【讨论】:

      【解决方案6】:

      基本上是@espascarello 和@adeneo 答案的promisified 版本,带有后备参数:

      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)

      2021 年 3 月编辑 在与@hitautodestruct 交谈后,我决定添加基于Promise 的函数的更“规范”版本。 onerror 案例现在被拒绝,但随后被捕获并返回默认值:

      function getImageOrFallback(url, fallback) {
        return new Promise((resolve, reject) => {
          const img = new Image()
          img.src = url
          img.onload = () => resolve(url)
          img.onerror = () => {
            reject(`image not found for url ${url}`)
          }
        }).catch(() => {
          return fallback
        })
      }
      
      getImageOrFallback("https://google.com", "https://picsum.photos/400/300").then(validUrl => {
        console.log(validUrl)
        document.body.style.backgroundImage = `url(${validUrl})`
      })
      html, body {
        height: 100%;
        background-repeat: no-repeat;
        background-position: 50% 50%;
        overflow-y: hidden;
      }

      注意:我个人可能更喜欢fetch 解决方案,但它有一个缺点——如果你的服务器以特定方式配置,它可以返回 200 / 304,即使文件不存在。另一方面,这将完成这项工作。

      【讨论】:

      • 对于fetch,可以使用response对象的ok属性判断请求是否成功:fetch(url).then(res =&gt; {if(res.ok){ /*exist*/} else {/*not exist*/}});
      • 不幸的是,如果我想检查有效的背景图像,这对我不起作用。 background-image: url('/a/broken/url') 给了我 200ok (Chrome 74)。
      • @HynekS 我建议在onerror 回调而不是resolve 中拒绝承诺。 new Promise( (resolve, reject) =&gt; { /*...*/ img.onerror = () =&gt; reject('Not found') } )
      • @hitautodestruct 我总是解决的原因,即使是在“错误”的情况下,是我经常在Promise.all() 中使用这种模式,其中拒绝一个项目会拒绝整个列表。另外,我 expect 它总是返回 something (现有图像 url:因此是函数名称)。虽然我不是 FP 极客,但我喜欢将其视为 Either monad。
      • @HynekS 您可能需要注意答案中Promise.all() 的使用。 IMO 如果您的答案是“承诺版本......”那么它应该尽可能接近经典承诺,否则可能会给不熟悉承诺的人造成混淆。此外,您可能需要考虑Promise.allSettled() 而不是Promise.all(),以免对任何reject 的所有承诺都失败。
      【解决方案7】:

      如果您创建一个图像标签并将其添加到 DOM,则应该触发其 onload 或 onerror 事件。如果 onerror 触发,则图像在服务器上不存在。

      【讨论】:

        【解决方案8】:

        你可以调用这个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;
            }
        }
        

        【讨论】:

        • 努力。但是在单个表单中加载多个图像时有点耗时。
        • 如果 url 不存在,它会在 xhr.send() 处显示错误。
        【解决方案9】:

        您可以通过设置相应图像文件夹的相对路径来使用您的 axios 执行此操作。我这样做是为了获取一个 json 文件。您可以对图像文件尝试相同的方法,您可以参考这些示例

        如果您已经将带有 baseurl 的 axios 实例设置为不同域中的服务器,则必须使用部署 Web 应用程序的静态文件服务器的完整路径。

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

        如果找到图像,则响应为 200,否则为 404。

        此外,如果图像文件存在于 src 内的 assets 文件夹中,您可以执行 require,获取路径并使用该路径执行上述调用。

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

        【讨论】:

          【解决方案10】:

          如果你使用 React,试试这个自定义的 Image 组件:

          import React, { useRef } from 'react';
          import PropTypes from 'prop-types';
          
          import defaultErrorImage from 'assets/images/default-placeholder-image.png';
          
          const Image = ({ src, alt, className, onErrorImage }) => {
            const imageEl = useRef(null);
            return (
              <img
                src={src}
                alt={alt}
                className={className}
                onError={() => {
                  imageEl.current.src = onErrorImage;
                }}
                ref={imageEl}
              />
            );
          };
          
          Image.defaultProps = {
            onErrorImage: defaultErrorImage,
          };
          
          Image.propTypes = {
            src: PropTypes.string.isRequired,
            alt: PropTypes.string.isRequired,
            className: PropTypes.string.isRequired,
            onErrorImage: PropTypes.string,
          };
          
          export default Image;
          

          【讨论】:

          • 这有帮助!谢谢!
          【解决方案11】:

          如果您想知道图像是否在文件夹中,这很好用

          function checkImage(var, extension){
            var image = new Image();
            var url_image = './folder/' + var + '.' + extension;
            image.src = url_image;
            if (image.width == 0) {
              return false;
            } else {
              return true;
            }
          }
          

          【讨论】:

          • 这个问题可能已经过时了(差不多 8 岁)。您还可以将最后一部分简化为return image.width !== 0
          • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
          【解决方案12】:

          这里只是Promise 函数版本的答案,true/false 返回值:

          img加载:

          async function imageExists(imgUrl) {
              if (!imgUrl) {
                  return false;
              }
              return new Promise(res => {
                  const image = new Image();
                  image.onload = () => res(true);
                  image.onerror = () => res(false);
                  image.src = imgUrl;
              });
          }
          
          // test
          (async () => {
            // true
            console.log(await imageExists('https://www.gstatic.com/webp/gallery3/1.png'));
            // false
            console.log(await imageExists('https://www.gstatic.com/webp/gallery3/DOES_NOT_EXIST_THERE.png'));
          })()

          使用XMLHttpRequest(数据较少,但可能会导致 cors 问题):

          async function fileExists(fileUrl) {
              if (!fileUrl) {
                  return false;
              }
              return new Promise(res => {
                  const http = new XMLHttpRequest();
                  http.open('HEAD', fileUrl, true);
                  http.send();
                  http.onload = () => {
                      res(http.status != 404);
                  };
                  http.onerror = () => {
                      res(false);
                  };
              });
          }
          
          // test
          (async () => {
            // true
            console.log(await fileExists('https://www.gstatic.com/webp/gallery3/1.png'));
            // false
            console.log(await fileExists('https://www.gstatic.com/webp/gallery3/DOES_NOT_EXIST_THERE.png'));
          })()

          使用 fetch(现代浏览器,数据较少,可能是 CORS 问题)

          async function fileExists(fileUrl) {
              if (!fileUrl) {
                  return false;
              }
              const res = await fetch(fileUrl, {
                method: 'HEAD',
              });
              return !!res.ok;
          }
          
          // test
          (async () => {
            // false
            console.log(await fileExists('https://www.gstatic.com/webp/gallery3/1.png'));
            // false
            console.log(await fileExists('https://www.gstatic.com/webp/gallery3/DOES_NOT_EXIST_THERE.png'));
            
          
          })()
          TypeScript 版本:
          async function imageExists(imgUrl: string | null | undefined): Promise<boolean> {
            if (!imgUrl) {
              return false;
            }
          
            return new Promise(res => {
              const image = new Image();
              image.onload = () => res(true);
              image.onerror = () => res(false);
              image.src = imgUrl;
            });
          }
          
          async function fileExists(fileUrl: string | null | undefined): Promise<boolean> {
            if (!fileUrl) {
              return false;
            }
          
            return new Promise(res => {
              const http = new XMLHttpRequest();
          
              http.open('HEAD', fileUrl, false);
              http.send();
              http.onload = () => {
                  res(http.status != 404);
              };
              http.onerror = () => {
                  res(false);
              };
          
            });
          }
          
          
          async function fileExists(fileUrl: string | null | undefined): Promise<boolean>  {
            if (!fileUrl) {
              return false;
            }
            const res = await fetch(fileUrl, {
              method: 'HEAD',
            });
          
            return !!res.ok;
          }
          

          【讨论】:

            【解决方案13】:

            我在通过 JS 显示用户图像时遇到了一些困难,有时可能会丢失。

            事实证明,当图片加载失败时,您可以在 html 中执行以下操作以显示特定图片

            &lt;img src="img/path/image.png" onerror="javascript:this.src='img/path/no-image.png'"&gt;

            只是想分享一下...也许这可以为您节省一些时间!

            【讨论】:

              【解决方案14】:

              这很好用:

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

              【讨论】:

              • 很确定这每次都返回 true?
              【解决方案15】:

              您可以参考this link 以使用 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'`;
                  } } ```
              

              【讨论】:

              • 我刚刚测试了这个。 它不起作用。它总是返回默认图像。 (可能是因为在您尝试测试图像宽度之前,浏览器没有时间发出 HTTP 请求并加载图像)。
              猜你喜欢
              • 2013-08-05
              • 2014-06-27
              • 2012-03-01
              • 1970-01-01
              • 2015-02-16
              • 2011-08-20
              • 2015-04-14
              • 1970-01-01
              • 2014-12-12
              相关资源
              最近更新 更多