1

I'm writing an app that requests user profile photos from Microsoft Graph. Everything goes through fine - the request returns with a 200 status code, there's clearly a large chunk of data that gets returned and everything seems okay at the outset. But when I actually try to insert the photo into an image tag, the browser refuses to display it. Now as I understand it, Graph returns the image as a jpeg binary, but every method I know of/have searched for to convert the image binary into a browser-displayable format has failed.

  • Using btoa produces this error:

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

  • Using a FileReader in the following manner (with TypeScript and jQuery) produces a result, but the browser still doesn't render it:

//Where photo is the data as a string
let blob = new Blob([photo], { type: "image/jpeg" });
let reader = new FileReader();
reader.addEventListener("load", (e: any) => {
    let imgSrc = e.target.result;
    $("img").attr("src", imgSrc);
});
reader.readAsDataURL(blob);
  • Using URL.createObjectURL like so also parses, but doesn't display anything

let blob = new Blob([photo], { type: "image/jpeg" });
let url = URL.createObjectURL(blob);
$("img").attr("src", url);
  • Trying various permutations on the type property like different image formats and 'octet-binary' in the blob constructor also fails. Besides, the image is obviously a JPEG since printing it out as a string in Chrome's debugger shows "JFIF" in the first several characters
  • Trying the custom hex-to-base64 function from the top answer to this question also fails: How to display binary data as image - extjs 4

$("img").attr("src", "data:image/jpeg;base64," + hexToBase64(photo));
  • And of course, just embedding the unmodified image binary as a data source also fails.

I'm completely out of ideas at this point. Anyone have any suggestions?

Community
  • 1
  • 1
gecslam
  • 11
  • 2

1 Answers1

0

I created a sample web app for people to play with the Graph APIs called Visual Graph Explorer. Once you log on to the web app with O365 credentials, you will see it start pulling down user photos. If you want to see the full source you can check it out on GitHub.

The code for displaying user photos looks like the following. I'm using angular here, but the key is to use the createObjectUrl method to convert the response data into a URL that can be rendered by the browser. This is very close to your second example.

graphPersonPhotoDirective.js

function successCallback(response) {
    var url = window.URL || window.webkitURL;
    var blobUrl = url.createObjectURL(response.data);
    $scope.myPhoto = blobUrl;
    Cache.save(blobUrl, $scope.personId);
}

graph-person-photo.html

<div class="circular-container">
    <div class="circular" style="background-image: url('{{myPhoto}}')"></div>
</div>

I hope this helps!

Doug Perkes
  • 135
  • 1
  • 7