【问题标题】:Angular 2 - Check if image url is valid or brokenAngular 2 - 检查图片网址是否有效或损坏
【发布时间】:2016-07-25 14:28:33
【问题描述】:

我正在从 API 获取大量图像 URL,并将它们显示在 Angular 2 Web 应用程序中。某些 URL 已损坏,我想将它们替换为本地存储在我的网络服务器上的默认图片。有没有人建议如何测试 url 并在状态码 404 的情况下替换损坏的图像?

谢谢!

【问题讨论】:

    标签: javascript angular


    【解决方案1】:

    监听图片元素的error事件:

    <img [src]="someUrl" (error)="updateUrl($event)">
    

    其中updateUrl(event) { ... }this.someUrl 分配了一个新值。

    Plunker example

    如果你只想签入代码,可以使用Checking if image does exists using javascript中解释的方法

    @Directive({
      selector: 'img[default]',
      host: {
        '(error)':'updateUrl()',
        '[src]':'src'
       }
    })
    class DefaultImage {
      @Input() src:string;
      @Input() default:string;
    
      updateUrl() {
        this.src = this.default;
      }
    }
    

    Directive Plunker example

    【讨论】:

    • 为什么会被否决? AFAIK 这是正确的方法,利用浏览器事件...
    • @GünterZöchbauer 有指令来处理这样的事情会很好吗..?有什么想法吗? +1
    • 你是对的。我不知何故错过了“默认图片”,并进行了一些计算以获得替代 URL。
    • 谢谢,它刚刚为我解决了一个带有图像的 IIS 相对路径问题。大老板!
    • /* Angular 11 */ @Directive({ selector: 'img[default]', }) export class DefaultImageDirective { constructor(private elem: ElementRef) { } @Input() default = 'assets/placeholder.png'; @HostListener('error') onError(): void { this.elem.nativeElement.src = this.default; } }
    【解决方案2】:

    您可以通过这种方式使用 onError 事件来处理 invalid urlbroken url

    <img [src]="invalidPath" onError="this.src='images/angular.png'"/> 
    

    这样就可以通过 onError 事件直接将 img 路径分配给 src

    【讨论】:

    • 至少检查一下plunker。我认为不是正确或不正确。它关于有一些其他的方式......你说什么?
    • 没有。我没有走错路,别担心。只是说也可以有一些其他的选择。这是其中之一。这样就可以直接指定路径了。
    • 谢谢@PankajParkar
    • 在 Angular 6 上运行良好
    • 在 Angular 8 和 9 上为我工作。感谢@micronyks。 ?
    【解决方案3】:

    我在 Angular 4 上的示例

    <img [src]="img" (error)="img.src = errorImg" #img>
    
    1. 其中 img - 图像路径;
    2. 错误 - 错误发出
    3. errorImg - 默认 img 的路径
    4. #img - 链接到 img 对象

    【讨论】:

    • 这是最干净的方法,没有任何问题
    • 如果您在 ngFor 中有图像标签,如何使 #img 链接(以及错误处理程序中的 img 引用)动态化?
    • 我赞成这个答案,因为它一开始似乎有效,然后我注意到浏览器一直在加载(在 Chrome 的选项卡中加载微调器),即使所有资产和图像都已正确完成加载。它可以工作,但是有这个烦人的无限加载问题。在编辑问题之前无法撤消我的投票。
    【解决方案4】:

    我使用 base64 加载微调器:

    <img [src]="photoContainer.photo.url | secure" onError="this.src='data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHdpZHRoPSI0MHB4IiBoZWlnaHQ9IjQwcHgiIHZpZXdCb3g9IjAgMCA0MCA0MCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3BhY2U9InByZXNlcnZlIiBzdHlsZT0iZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEuNDE0MjE7IiB4PSIwcHgiIHk9IjBweCI+CiAgICA8ZGVmcz4KICAgICAgICA8c3R5bGUgdHlwZT0idGV4dC9jc3MiPjwhW0NEQVRBWwogICAgICAgICAgICBALXdlYmtpdC1rZXlmcmFtZXMgc3BpbiB7CiAgICAgICAgICAgICAgZnJvbSB7CiAgICAgICAgICAgICAgICAtd2Via2l0LXRyYW5zZm9ybTogcm90YXRlKDBkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRvIHsKICAgICAgICAgICAgICAgIC13ZWJraXQtdHJhbnNmb3JtOiByb3RhdGUoLTM1OWRlZykKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgQGtleWZyYW1lcyBzcGluIHsKICAgICAgICAgICAgICBmcm9tIHsKICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogcm90YXRlKDBkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRvIHsKICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogcm90YXRlKC0zNTlkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHN2ZyB7CiAgICAgICAgICAgICAgICAtd2Via2l0LXRyYW5zZm9ybS1vcmlnaW46IDUwJSA1MCU7CiAgICAgICAgICAgICAgICAtd2Via2l0LWFuaW1hdGlvbjogc3BpbiAxLjVzIGxpbmVhciBpbmZpbml0ZTsKICAgICAgICAgICAgICAgIC13ZWJraXQtYmFja2ZhY2UtdmlzaWJpbGl0eTogaGlkZGVuOwogICAgICAgICAgICAgICAgYW5pbWF0aW9uOiBzcGluIDEuNXMgbGluZWFyIGluZmluaXRlOwogICAgICAgICAgICB9CiAgICAgICAgXV0+PC9zdHlsZT4KICAgIDwvZGVmcz4KICAgIDxnIGlkPSJvdXRlciI+CiAgICAgICAgPGc+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMCwwQzIyLjIwNTgsMCAyMy45OTM5LDEuNzg4MTMgMjMuOTkzOSwzLjk5MzlDMjMuOTkzOSw2LjE5OTY4IDIyLjIwNTgsNy45ODc4MSAyMCw3Ljk4NzgxQzE3Ljc5NDIsNy45ODc4MSAxNi4wMDYxLDYuMTk5NjggMTYuMDA2MSwzLjk5MzlDMTYuMDA2MSwxLjc4ODEzIDE3Ljc5NDIsMCAyMCwwWiIgc3R5bGU9ImZpbGw6YmxhY2s7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNNS44NTc4Niw1Ljg1Nzg2QzcuNDE3NTgsNC4yOTgxNSA5Ljk0NjM4LDQuMjk4MTUgMTEuNTA2MSw1Ljg1Nzg2QzEzLjA2NTgsNy40MTc1OCAxMy4wNjU4LDkuOTQ2MzggMTEuNTA2MSwxMS41MDYxQzkuOTQ2MzgsMTMuMDY1OCA3LjQxNzU4LDEzLjA2NTggNS44NTc4NiwxMS41MDYxQzQuMjk4MTUsOS45NDYzOCA0LjI5ODE1LDcuNDE3NTggNS44NTc4Niw1Ljg1Nzg2WiIgc3R5bGU9ImZpbGw6cmdiKDIxMCwyMTAsMjEwKTsiLz4KICAgICAgICA8L2c+CiAgICAgICAgPGc+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMCwzMi4wMTIyQzIyLjIwNTgsMzIuMDEyMiAyMy45OTM5LDMzLjgwMDMgMjMuOTkzOSwzNi4wMDYxQzIzLjk5MzksMzguMjExOSAyMi4yMDU4LDQwIDIwLDQwQzE3Ljc5NDIsNDAgMTYuMDA2MSwzOC4yMTE5IDE2LjAwNjEsMzYuMDA2MUMxNi4wMDYxLDMzLjgwMDMgMTcuNzk0MiwzMi4wMTIyIDIwLDMyLjAxMjJaIiBzdHlsZT0iZmlsbDpyZ2IoMTMwLDEzMCwxMzApOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTI4LjQ5MzksMjguNDkzOUMzMC4wNTM2LDI2LjkzNDIgMzIuNTgyNCwyNi45MzQyIDM0LjE0MjEsMjguNDkzOUMzNS43MDE5LDMwLjA1MzYgMzUuNzAxOSwzMi41ODI0IDM0LjE0MjEsMzQuMTQyMUMzMi41ODI0LDM1LjcwMTkgMzAuMDUzNiwzNS43MDE5IDI4LjQ5MzksMzQuMTQyMUMyNi45MzQyLDMyLjU4MjQgMjYuOTM0MiwzMC4wNTM2IDI4LjQ5MzksMjguNDkzOVoiIHN0eWxlPSJmaWxsOnJnYigxMDEsMTAxLDEwMSk7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNMy45OTM5LDE2LjAwNjFDNi4xOTk2OCwxNi4wMDYxIDcuOTg3ODEsMTcuNzk0MiA3Ljk4NzgxLDIwQzcuOTg3ODEsMjIuMjA1OCA2LjE5OTY4LDIzLjk5MzkgMy45OTM5LDIzLjk5MzlDMS43ODgxMywyMy45OTM5IDAsMjIuMjA1OCAwLDIwQzAsMTcuNzk0MiAxLjc4ODEzLDE2LjAwNjEgMy45OTM5LDE2LjAwNjFaIiBzdHlsZT0iZmlsbDpyZ2IoMTg3LDE4NywxODcpOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTUuODU3ODYsMjguNDkzOUM3LjQxNzU4LDI2LjkzNDIgOS45NDYzOCwyNi45MzQyIDExLjUwNjEsMjguNDkzOUMxMy4wNjU4LDMwLjA1MzYgMTMuMDY1OCwzMi41ODI0IDExLjUwNjEsMzQuMTQyMUM5Ljk0NjM4LDM1LjcwMTkgNy40MTc1OCwzNS43MDE5IDUuODU3ODYsMzQuMTQyMUM0LjI5ODE1LDMyLjU4MjQgNC4yOTgxNSwzMC4wNTM2IDUuODU3ODYsMjguNDkzOVoiIHN0eWxlPSJmaWxsOnJnYigxNjQsMTY0LDE2NCk7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNMzYuMDA2MSwxNi4wMDYxQzM4LjIxMTksMTYuMDA2MSA0MCwxNy43OTQyIDQwLDIwQzQwLDIyLjIwNTggMzguMjExOSwyMy45OTM5IDM2LjAwNjEsMjMuOTkzOUMzMy44MDAzLDIzLjk5MzkgMzIuMDEyMiwyMi4yMDU4IDMyLjAxMjIsMjBDMzIuMDEyMiwxNy43OTQyIDMzLjgwMDMsMTYuMDA2MSAzNi4wMDYxLDE2LjAwNjFaIiBzdHlsZT0iZmlsbDpyZ2IoNzQsNzQsNzQpOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTI4LjQ5MzksNS44NTc4NkMzMC4wNTM2LDQuMjk4MTUgMzIuNTgyNCw0LjI5ODE1IDM0LjE0MjEsNS44NTc4NkMzNS43MDE5LDcuNDE3NTggMzUuNzAxOSw5Ljk0NjM4IDM0LjE0MjEsMTEuNTA2MUMzMi41ODI0LDEzLjA2NTggMzAuMDUzNiwxMy4wNjU4IDI4LjQ5MzksMTEuNTA2MUMyNi45MzQyLDkuOTQ2MzggMjYuOTM0Miw3LjQxNzU4IDI4LjQ5MzksNS44NTc4NloiIHN0eWxlPSJmaWxsOnJnYig1MCw1MCw1MCk7Ii8+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4K'">
    

    【讨论】:

      【解决方案5】:

      我找到了一个对我有用的非常简单的解决方案。这不会检查 404,但是我有可能具有 .image 属性的对象。我知道这不是他问题的答案,但希望它可以帮助一些人。

      <img class="list-thumb-img" [attr.src]="item.image?.url ? item.image.url : 'assets/img/140-100.png'">
      

      【讨论】:

      • 是的。它是最简单的解决方案。谢谢
      【解决方案6】:

      一个完美的 Angular 8 指令:

      import {AfterViewInit, Directive, ElementRef, Input} from '@angular/core';
      
      @Directive({
          selector: '[appImage]'
      })
      export class ImageDirective implements AfterViewInit {
      
          @Input() src;
      
          constructor(private imageRef: ElementRef) {
          }
      
          ngAfterViewInit(): void {
              const img = new Image();
              img.onload = () => {
                  this.setImage(this.src);
              };
      
              img.onerror = () => {
                  // Set a placeholder image 
                  this.setImage('assets/placeholder.png');
              };
      
              img.src = this.src;
          }
      
          private setImage(src: string) {
              this.imageRef.nativeElement.setAttribute('src', src);
          }
      }
      

      现在,HTML 将是:

      <img [src]="'/some/valid-image.png'" appImage>
      

      【讨论】:

      • 它没有应用指令。我创建了指令但没有工作!!
      【解决方案7】:

      如果要更改未加载的图像或源已损坏... Angular 8,只需将此目标的 src 更改为默认资产:

      • 组件 HTML

        <...>

      • 组件 TS

        pictNotLoading(事件) { event.target.src = 'assets/nopicture.png'; }

      【讨论】:

        【解决方案8】:

        这是我在多图像上的后备解决方案。 我们基本上在解析图像后分离 ChangeDetector,以便在解析图像后减少 CPU 的 vm 检查周期。

        import {Component, ChangeDetectionStrategy, ChangeDetectorRef} from 'angular2/core';
        import {AppStore} from "angular2-redux-util/dist/index";
        
        
        
        @Component({
            selector: 'logoCompany',
            changeDetection: ChangeDetectionStrategy.Default,
            template: `
                    <div style="padding-top: 7px" > 
                      <span style="color: gainsboro; font-family: Roboto">{{getBusinessInfo('companyName')}}</span>
                      <!--<img style="width: 35px" class="img-circle" src="http://galaxy.example.me/Resources/Resellers/{{getBusinessInfo('businessId')}}/{{getBusinessInfo('fileName')}}" />-->
                      <img style="width: 35px" class="img-circle" [src]="getImageUrl()" (load)="onImageLoaded()" (error)="onImageError()" />
                    </div>
            `
        })
        
        export class LogoCompany {
        
            constructor(private cdr:ChangeDetectorRef) {    
            }
            private imageRetries:number = 0;
            private unsub;
        
        
            private detach() {
                this.cdr.detach();
            }
        
            private getImageUrl() {          
                var url = '';
                switch (this.imageRetries){
                    case 0: {
                        url = 'http://galaxy.example.me/Resources/Resellers/' + this.getBusinessInfo('businessId') + '/Logo.jpg'
                        break;
                    }
                    case 1: {
                        url = 'http://galaxy.example.me/Resources/Resellers/' + this.getBusinessInfo('businessId') + '/Logo.png'
                        break;
                    }
                    default: {
                        url = 'assets/person.png'
                        break;
                    }
        
                }
                return url;
            }
        
            private onImageLoaded() {
                this.detach();
            }
        
            private onImageError() {
                this.imageRetries++;
            }
        
            private getBusinessInfo(field):string {
                  return '12345';
            }
        
        
        
        
        
        }
        

        【讨论】:

          【解决方案9】:

          只有当 url 不正确时才会发生错误事件, 如果 url 正确但文件不存在,则可以在此代码中使用

          javascript check if file exists on server:

          (注意404是数字而不是字符串)

          function doesFileExist(urlToFile) {
          var xhr = new XMLHttpRequest();
          xhr.open('HEAD', urlToFile, false);
          xhr.send();
           
          if (xhr.status == 404) {
              return false;
          } else {
              return true;
          }}
          

          【讨论】:

            【解决方案10】:

            对于这个用例,您可以简单地使用三元运算符。 我假设您正在从远程服务器获取响应

            <img src="{{ res.image ? res.image : onErrorFunction() }}"
            

            如果您不想让来自服务器的图像在单引号 '' 中写入路径。

            这里如果链接被破坏,那么它将转到 onErrorFunction 如果它没有被破坏,res.image 将被加载。

            【讨论】:

              猜你喜欢
              • 2016-08-29
              • 2017-09-28
              • 1970-01-01
              • 2012-04-13
              • 2017-09-13
              • 1970-01-01
              • 2019-09-16
              • 1970-01-01
              • 2013-01-05
              相关资源
              最近更新 更多