Ben Cameron
Ben Cameron

Reputation: 4433

Angular 2 - render byte[] from Web Api as an image src

I have an Angular 2 app that is connecting to a Web Api backend. There is an endpoint that returns a byte[] of an image that is stored in a sql database. How can I display this as an image in Angular? I can change either the Web Api or Angular app.

My Web Api endpoint looks like this...

[Route("api/profileimage/{userId}")]
public byte[] Get(string userId)
{
    var image = _profileImageService.GetProfileImage(userId);

    return image;
}

And my Angular HTML looks like this...

<img src="http://localhost:2116/api/ProfileImage/{{tile.UserId}}" width="100" height="100"/>

What conversion do I need to do, or what should the api serve up?

Upvotes: 9

Views: 34485

Answers (2)

Ahmed Elkoussy
Ahmed Elkoussy

Reputation: 8568

So the accepted answer by rinukkusu is very helpful & detailed but you don't have to:

1- Neither make a directive (but you can of course)

2- Nor to use the sanitizer service & make an sanitization exception

I was a little bit overwhelmed by those two tasks, especially bypassing the sanitization, so I will write the simplest way to handle this safely

You can simply use the following method (in generic way):

1- Return the image from your backend as base64 encoded string

2- Recieve that base64 string of the image in Angular 2+ & build the following string property in your typescript file then safely use it in your html directly without using the sanitizer service

// so for example you will get the image for example in this dataService.ts

this.http.get(this.api_url + 'image').subscribe(response => {
    this.image = response['image'];
    this.imageSrc = 'data:image/jpeg;base64,' + this.image;
});

Then in your html file , you can use the imageSrc property directly (for example from the injected dataService that have the property ready)

<img id="image" [src]="dataService.imageSrc" width="100" height="50">

I hope this helps someone else & many thanks for rinukkusu as his answer helped me personally

Upvotes: 15

Maximilian Riegler
Maximilian Riegler

Reputation: 23506

Convert the image to Base64 on your server:

[Route("api/profileimage/{userId}")]
public string Get(string userId)
{
    var image = _profileImageService.GetProfileImage(userId);

    return System.Convert.ToBase64String(image);
}

For ease of use I created a new directive to encapsulate all the code we need for getting and displaying the image:

import {Directive, OnInit, Input} from '@angular/core';
import {Http} from '@angular/http';
import {BROWSER_SANITIZATION_PROVIDERS, DomSanitizationService} from '@angular/platform-browser';

@Directive({
  selector: '[profile-image]',
  providers: [BROWSER_SANITIZATION_PROVIDERS],
  host: {
    '[src]': 'sanitizedImageData'
  }
})
export class ProfileImageDirective implements OnInit {
  imageData: any;
  sanitizedImageData: any;
  @Input('profile-image') profileId: number;

  constructor(private http: Http,
              private sanitizer: DomSanitizationService) { }

  ngOnInit() {        
    this.http.get("http://localhost:2116/api/ProfileImage/" + profileId)
      .map(image => image.text())
      .subscribe(
        data => {
          this.imageData = 'data:image/png;base64,' + data;
          this.sanitzedImageData = sanitizer.bypassSecurityTrustUrl(imageData);
        }
      );
  }
}

In your template include it like this:

<img [profile-image]="tile.UserId" width="100" height="100" />

Don' forget to add the directive to the directives array of your component.


Working Plunker for example usage

Upvotes: 29

Related Questions