Convert Blob to image url and use in image src to display image
Asked Answered
A

5

13

How to convert blob to base64/image?
I am getting this blob through API call and I am trying to display it in a
image. I have tried with stackoverflow answers but nothing could help so
I just tried this.

//Angular 5 code  
imageSrc;//global variable  
data = [{"image_blob":{"type":"img/jpg","data":[123,125]}}];//from api  
var blob1 = new Blob([new Uint8Array(data[0].image_blob.data)]);  
const imageUrl = URL.createObjectURL(blob1);  
console.log(imageUrl);//blob:http://localhost:8100/c489.etc  
this.imageSrc = imageUrl;  

<!-- html code -->  
<img [src]='imageSrc' alt="image">  

Have missed anything. Please suggest

Anaxagoras answered 25/6, 2018 at 8:47 Comment(4)
Possible duplicate of Convert blob to base64Conjoined
No, I had tried with that code too.. but no luck. After trying this for 7 days posted the question. I had removed the angular sanitation issue too. In order to keep it simple dint mention here.Anaxagoras
What is your main problem? Getting the base64 or putting it in the html?Conjoined
Putting in html, anyhow I had converted to imageurl. But thats not workingAnaxagoras
C
14

Generate the base64 string:

var reader = new FileReader();
reader.readAsDataURL(blob); 
reader.onloadend = function() {
   base64data = reader.result;     
}

Once you have it, generate the string you'll put in you image src with Angular sanitizer. Example:

import { DomSanitizer } from '@angular/platform-browser';
constructor( ... private sanitizer : DomSanitizer ...){}

public myFunction() : void {
    let mySrc = this.sanitizer.bypassSecurityTrustUrl('data:image/png;base64,' + base64data);
}

You can modify the type 'data:image/png;base64,' as you need.

And to finish, put this in your image:

<img [src]="mySrc" />
Conjoined answered 25/6, 2018 at 9:6 Comment(2)
powkachu thanks for this, but tried all the above methods. In fact I had created the Pipe for sanitization. But nothing working.Anaxagoras
Oh really, that's weird... The image shows nothing? Did you check if your base64 string is well generated?Conjoined
I
14

When trying to load an image as a blob from a server response I ran into the issue that Angular2 (7) is considering the provided url as unsafe. When searching for a solution the widely suggested solution is to use DomSanitizer to bypass the security.

See example from @Amirreza here, but also in other StackOverflow posts the same solution is suggested.

On the angular documentation page for DomSanitizer they write the following:

bypassSecurityTrustUrl()

WARNING: calling this method with untrusted user data exposes your application to XSS security risks!

Seems to me that it is not safe to do so, unless you are really really sure that the image source can be trusted!
You should consider that even if the source comes from your own server, it might have been uploaded by a user and it would be possible to exploit such a solution by uploading a malicious image.

It is better and more secure to convert the blob (image) into a data-url (a base64 string) and set that as the src for your image element.

Data URLs are generally considered safe (MDN):

Encoding data into base64 format

base64 strings are generally url-safe, and that's why they can be used to encode data in Data URLs.

This solution is also suggested in the blog post here and even in the other answer from @Powkachu, but in that answer the mistake is that the base64 protocol identifier is added double (the FileReader::readAsDataURL already returns this in the result) and unnecessarily passed to the bypassSecurityTrustUrl from the sanitizer.

The correct, secure and more simple solution would look like this:

let mySrc;
const reader = new FileReader();
reader.readAsDataURL(blob); 
reader.onloadend = function() {
   // result includes identifier 'data:image/png;base64,' plus the base64 data
   mySrc = reader.result;     
}

Where blob is a Blob and mySrc is a dataUrl (base64 string) that now can be set as image src immediately:

<img [src]="mySrc" />

Here a fiddle in plain Javascript to demonstrate the workings of this solution without Angular.

Interflow answered 16/5, 2019 at 13:30 Comment(2)
Thanks for the help.Mortarboard
It solved my issue, I think this should be marked as the correct answerHalinahalite
C
4

this line works for me correctly, i haven't tested completely, and do not know about security issues or any other stuff, but it seems right:

this.ImageSource = window.URL.createObjectURL(blob);

and in html

<img [src]="ImageSource" />

Update 1:

It has security issue, browser exception about unsafe url

Update 2

problem solved, my problem was, duplicate information for Blob, so just, removed unneeded text, (i think because i had set mime correctly, that information was already there)]

var result = (<any>e.srcElement).result;
  //this.Content = this.sanitizer.bypassSecurityTrustUrl('data:image/' + this.File.FileType + ';base64,' + result);
  this.Content = this.sanitizer.bypassSecurityTrustUrl(result);
Ceremonious answered 9/10, 2018 at 3:56 Comment(0)
T
2

What did worked to me was this

let blob = new Blob([response] );
                this.srcImage = this._sanitizer.bypassSecurityTrustUrl(window.URL.createObjectURL(blob));

I used the same principle to download a file from blob and it's working fine.

downloadFileView(data, fileName) {
        let blob:any = new Blob([data] );
        const url= window.URL.createObjectURL(blob);
        let a = document.createElement('a');
        a.href = url;
        a.download = fileName;
        a.click();
        window.URL.revokeObjectURL(url);
        a.remove();
    }

The sanitazier service is important if you want to see the image and avoid the browser's warning.

Hope this works for you

Tigerish answered 15/9, 2020 at 3:30 Comment(0)
S
1

Thank you for Everyone! I just want to share my final solution ( I use angular 17 now)

backendservice :

const url = this.url + "/images/" + picturetype + "/" + Id;
    let options = {
    headers: this.getHeaders(),
    responseType: "blob" as "json"
  };
  return this.httpClient.get<Blob>(url, options).pipe(
   map(response => {
    console.log("respons" , response);
    
    let dataType = response.type;
    let binaryData = [];
    binaryData.push(response);
    let result: [any[], string] = [binaryData, dataType]
    console.log("result" , result);
    return new Ok(result);
   
  }),
  catchError(error => of(new Err<[any[], string]>(error)))

ts:

   this.backendService.getPicture(picturetype,Id).subscribe((result) => {
   if (result.isErr()) {
     console.error(result.unwrapErr());
     return;
   }
   let response = result.unwrap();
   let data = response[0];
   let dataType = response[1]; 
      
   // this is the magic line!!!
    this.mySrc = 
    this.sanitizer.bypassSecurityTrustUrl(window.URL.createObjectURL(new 
    Blob(data, { type: dataType })));  
    
   });

html:

   [src]="this.mySrc"
Shannon answered 23/4 at 15:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.