0

I'm working on Angular4 project. I get Blob returned from my API call, then I convert it to base64 but can't manage to save it to the array of pictures (so I can show it with *ngFor later).

Here is my API call:

getImg(): Observable<Blob> { const path = *can't show this part*; return this.http.get(path, { responseType: "blob" }); }

And here is what I tried so far:

This function has error at line this.images[i] = reader.result;, because it says Property 'images' does not exist on type 'FileReader'

images: Array<any> = [];

getImages(): void {
for (var i = 0; i < this.myData.length; i++) {
  this.myApiCalls.getImg()
    .subscribe(res => {
      var reader = new FileReader();
      reader.readAsDataURL(res);
      reader.addEventListener("loadend", function () {
        this.images[i] = reader.result;
      });       
    },
      err => {
        console.log(err.message)
      });
  }
}

The other thing I tried is with callbacks, but I still got error, on the same column but for different thing. It says 'this' implicitly has type 'any' because it does not have a type annotation.

getImages(): void {
for (var i = 0; i < this.myData.length; i++) {
  this.myApiCalls.getImg()
    .subscribe(res => {
      this.readImageFile(res, function(e: any) {
        this.fields[i] = e.target.result;
      });       
    },
      err => {
        console.log(err.message)
      });
  }
}

readImageFile(response: Blob, callback: any): void {
   var reader = new FileReader();
   reader.readAsDataURL(response);
   reader.onloadend = callback 
} 

So I get data returned back correctly, but the problem is I can't manage to save it to the array. If you guys are able to help me solve that problem I would be very happy. Thank you.

HC1122
  • 404
  • 1
  • 6
  • 19

3 Answers3

1

Here is updated your code please try this once.

images: any[]= [];

getImages(): void {
for (var i = 0; i < this.myData.length; i++) {
  this.myApiCalls.getImg()
    .subscribe(res => {
      this.readImageFile(i,res);
    },
      err => {
        console.log(err.message)
      });
  }
//here iam logged console. See values saved array or not.
console.log("Print your Value here once",this.images);
}

readImageFile(indexVal:number,response: Blob): void {
      let self = this;
      var reader = new FileReader();
      reader.readAsDataURL(response);
      reader.onloadend = function () {
          self.images[indexVal] = reader.result;
        }
} 

Try this once and let me know. I hope its useful to solve your problem. I all ready worked related this function

Thanks,

Muthukumar

Karnan Muthukumar
  • 1,843
  • 1
  • 8
  • 15
1

Why are you converting it to a base64? You can create a url from the blob with const blobUrl = URL.createObjectURL(blob) (just remember to revoke the url to free mem after it's not used with URL.revokeObjectURL(blobUrl))? I ask because it's more efficient.

But your code is failing because of a context issue (this is not what you expect). The context inside the callback is the reader object. There's a clue in the error Property 'images' does not exist on type 'FileReader' - it's showing that this is an instance of FileReader.

Edit: You should also use let on your loop i, otherwise i won't be what you expect inside the callback.

If you want to preserve the outer scope context then use an arrow function:

getImages(): void {
for (let i = 0; i < this.myData.length; i++) {
  this.myApiCalls.getImg()
    .subscribe(res => {
      var reader = new FileReader();
      reader.addEventListener("load", () => {
        this.images[i] = reader.result;
      });
      reader.readAsDataURL(res);
    },
      err => {
        console.log(err.message)
      });
  }
}
Dominic
  • 62,658
  • 20
  • 139
  • 163
0

Try this answer, it may be helpful https://stackoverflow.com/a/16245768/8350917