Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

My task is to make async image requests with auth headers. I have image paths like this:

<img src="{{file.src}}"/>

And I need to Add Bearer Token to header for such requests. Page contains many images, so ajax requests are don't fit. Have no idea how to do this.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
349 views
Welcome To Ask or Share your Answers For Others

1 Answer

Assuming you have implemented an HttpIntercepter to add the header, here's a solution that actually does work (in Angular 4):

import { Pipe, PipeTransform } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

@Pipe({
  name: 'secure'
})
export class SecurePipe implements PipeTransform {

  constructor(private http: HttpClient) { }

  transform(url: string) {

    return new Observable<string>((observer) => {
      // This is a tiny blank image
      observer.next('data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==');

      // The next and error callbacks from the observer
      const {next, error} = observer;

      this.http.get(url, {responseType: 'blob'}).subscribe(response => {
        const reader = new FileReader();
        reader.readAsDataURL(response);
        reader.onloadend = function() {
          observer.next(reader.result);
        };
      });

      return {unsubscribe() {  }};
    });
  }
}

You use it like this:

<img [src]="'/api/image/42' | secure | async" />

The previous solutions were pretty drastically flawed. I don't guarantee that this is perfect, but it is actually tested and working for me.

You can't return the observable you get from http.get! I don't know why the previous solutions assume you can. The observable for http.get indicates when the data is retrieved from the server. But, there is another asynchronous process that has to be completed after that: the call to reader.readAsDataURL. So you need to create an Observable that you will call next on after that process completes.

Also, if you don't put something into the image immediately, the browser will still try to load the image using HTTP and you get an error in your JavaScript console. That's the reason for the first observer.next call that puts in an empty, tiny GIF image.

An issue with this approach is that if the image is used more than once it will load each one every time. Even if the browser caches, you do the conversion to base64 every single time. I created a cache that stores the image so that future queries are not needed after the first.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...