Jacob
Jacob

Reputation: 57

Angular 8/9 - Getting image via service and showing it on screen without a url

I have an api call that returns a document of type: content-type
image/png

The image is sent back, but there is not url it just sends back the entire image object. If the api is called directly on a browser it just shows the image directly.

I want to be able to have a service that gets this image and show it in a component.

image-data.ts

import { Observable } from 'rxjs';

export interface ImageInfo {
    image: Image
}

export abstract class ImageData {
  abstract getImageData(): Observable<ImageInfo>;
}

image-data-service.ts

import { Injectable } from '@angular/core';
import { of as observableOf, Observable } from 'rxjs';
import { ImageInfo, ImageData } from '../data/image-data';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';

@Injectable()
export class ImageDataService extends ImageData {


    baseurl = 'https://website.com/image';
    httpOptions = {
        headers: new HttpHeaders({
          'Content-Type': 'image/png'
        })
      }

    constructor(private http: HttpClient) {
        super();
    }

  private imageInfoData: ImageInfo = 
    {
        image: Image
    }


    getImageData(): Observable<ImageInfo> {
        return this.http.get<ImageInfo>(this.baseurl)
        .pipe(
          retry(1),
          catchError(this.errorHandl)
        )
  }

   // Error handling
   errorHandl(error) {
    let errorMessage = '';
    if(error.error instanceof ErrorEvent) {
      // Get client-side error
      errorMessage = error.error.message;
    } else {
      // Get server-side error
      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
    }
    console.log(errorMessage);
    return throwError(errorMessage);
 }
}

in the component to show the image I am trying:

   this.imageDataService.getImageData()
      .pipe(takeWhile(() => this.alive))
      .subscribe((ImageData) => {
        this.imageData = imageData;

      });

Then in the components html I want to display the image:

<img [src]="imageData"> 
// Not sure if I should set the src because I get back the entire image not the url

Upvotes: 3

Views: 10879

Answers (3)

Cagri Tacyildiz
Cagri Tacyildiz

Reputation: 17590

Set the response type to be BLOB in header option

   {responseType: 'blob'}

so that we get the image in binary format

then

import { DomSanitizer, SafeUrl } from '@angular/platform-browser';

then in costructor put

private sanitizer: DomSanitizer

then in your success call of service

this.imageData = this.sanitizer.bypassSecurityTrustUrl(
            urlCreator.createObjectURL(blob));

Upvotes: 6

Sayooj V R
Sayooj V R

Reputation: 2363

Please try like this

in html

<img [src]="imageToShow"
     alt="Place image title"
     *ngIf="!isImageLoading; else noImageFound">
<ng-template #noImageFound>
     <img src="fallbackImage.png" alt="Fallbackimage">
</ng-template>

in service

getImageData(): Observable<ImageInfo> {
return this.httpClient.get(imageUrl, { responseType: 'blob' })
.pipe(
  retry(1),
  catchError(this.errorHandl)
)}

in component

  imageToShow: any;
  isImageLoading: boolean;
createImageFromBlob(image: Blob) {
   let reader = new FileReader();
   reader.addEventListener("load", () => {
      this.imageToShow = reader.result;
   }, false);

   if (image) {
      reader.readAsDataURL(image);
   }
  }



    getImageFromService() {
      this.isImageLoading = true;
      this.imageService.getImage(this.imgUrl).subscribe(data => {
        this.createImageFromBlob(data);
        this.isImageLoading = false;
      }, error => {
        this.isImageLoading = false;
        console.log(error);
      });
  }


    ngOnInit(){
     this.getImageFromService()
   }

Upvotes: 3

kacase
kacase

Reputation: 2859

You need to create an image that the frontend can use before applying it as src.

Assuming you get a blob returned from your service, you can do something similar to this:

imageToShow: any;

createImageFromBlob(image: Blob) {
   let reader = new FileReader();
   reader.addEventListener("load", () => {
      this.imageToShow = reader.result;
   }, false);

   if (image) {
      reader.readAsDataURL(image);
   }
}

And then use the generated image in your src:

<img [src]="imageToShow">

Upvotes: 1

Related Questions