3

I do apologize that this is a very specific question, but I'm desperate and I'd appreciate any hints/directions.

The scenario is the following: I'm making an HTTP GET request to retrieve a profilePhoto and update the image profile in my Angular application.

This is my graph.service:

import { Injectable } from "@angular/core";
import { Http, Headers } from "@angular/http";
import { AdalService } from "../adal/adal.service";

@Injectable()
export class GraphService {
  private graphUri = "https://graph.microsoft.com/v1.0/";

  constructor(private http: Http, private adalService: AdalService) {}

  public userPhoto(upn: string) {
    return this.http
      .get(
        this.graphUri +
          "users/" +
          this.adalService.userInfo.profile.upn +
          "/photo/$value",
        { headers: this.headers() }
      )
      .map(res => res);
  }

  private headers() {
    const headers = new Headers();
    headers.set("Authorization", this.adalService.token);
    return headers;
  }
}

On the home.component where I'm intending to use it, I have:

this.graphService.userPhoto().subscribe(resp => {
  if (resp.status === 200) {
    const dataToString = resp.arrayBuffer();
    const fileReader = new FileReader();
    fileReader.readAsArrayBuffer(dataToString);
    // Here there's an error:
    // 'Argument of type Array Buffer is not assignable
    //  to parameter of type Blob.
    const image = "data:image/jpeg;base64," + dataToString;
    document.getElementById("photo").setAttribute("src", image);
  }
});

I don't even know if I'm on the right path, to be honest... I've read somewhere about FileReader. But at first, this was my attempt:

this.graphService.userPhoto().subscribe(resp => {
  if (resp.status === 200) {
    const dataToString = resp.text();
    const image = "data:image/jpeg;base64," + btoa(encodeURI(dataToString));
    document.getElementById("photo").setAttribute("src", image);
  }
});

dataToString contains something like: ����JFIF``��C which I understand it to be the binary data.

Just to be clear, the GET request returns 200, the bearer token is valid. I'm just somehow failing to display it...

What am I doing wrong? How one should approach it?

Many thanks!

Edit 1: @RasmusW - The only reason of why I've added the encodeURI call is because without it I'll get the following error:

ERROR DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.

With the encodeURI my img HTML tag will look something like that:

<img _ngcontent-c2="" id="photo" src="data:image/jpeg;base64, JUVGJUJGJUJEJUVGJUJGJUJEJUVGJUJGJUJEJUVGJUJGJUJEJTAwJTEw(shortened)">

However, the image doesn't display.

AuroMetal
  • 928
  • 3
  • 14
  • 32
  • I'm no javascript expert, but it seems that if ``dataToString`` contains the JPEG file (as per the JFIF information), then the problem must be in the image base64 conversion. I think you the ``encodeURI`` call is unnecessary, because ``btoa`` will take the binary and covert to base64. Also, in the places I looked, there is a space between the comma after "base64" and the base64 encoded image. – RasmusW Feb 14 '18 at 11:22
  • Hi @RasmusW, thanks for the reply. If you could please have a look at my Edit 1, I've explained in detail the reason why the `encodeURI`. – AuroMetal Feb 14 '18 at 14:38

1 Answers1

4

You need a base64 encoded representation of the image. This isn't simply the binary data converted to a string.

In order to get this to work, you need to tell Angular to expect a Blob using the responseType parameter. This lets it know not to attempt to parse it as JSON. You convert that blob into a data URI.

There are several explanations of how this works (with examples) on Stack Overflow:

Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63