Reputation: 4433
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
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
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