1
votes

Having a look into Microsoft's Graph API, specifically looking at the angular example called 'O365-Angular-Microsoft-Graph-Connect' - https://github.com/OfficeDev/O365-Angular-Microsoft-Graph-Connect. Have successfully registered the app and installed the dependencies. However when running the app I am correctly seeing all the user's details apart from the image, (all the users in our O365 tenancy have an image). Debugging the app it appears the response received from the api is full of '�' symbols which suggests an encoding issue somewhere. When using the graph API explorer I get the image returned fine which suggests this is the app. Any ideas of how to remedy this so the example app works? The index html page is correctly UTF-8 encoded so the app looks correct to me which suggests an issue with the API, however as the graph API explorer gives me the correct image that suggests it's the app.

Any ideas on how to pull through the image in the example app provided by Microsoft?

Other thoughts are that as the example screenshot provided by MS uses a placeholder image this part of the app is simply not working yet.

4
This seems very strange. Can you provide a fiddler trace (you can remove user token from the trace) please?Dan Kershaw - MSFT
@RichW - did you happen to find solution for this? I have the same "problem" - docs says it is binary JPEG image but I can not get it working... graph.microsoft.io/en-us/docs/api-reference/v1.0/api/… Contains the binary data of the requested photo. The HTTP response code is 200.nettutvikler

4 Answers

1
votes

After playing with Postman (Chrome extension for playing with REST etc.) it is very clear that the returned image is ok and "normal" and that our code must make sure it is saved as it should be.

Afterwards I hacked this NodeJS code that can, maybe, help another newbies like me:)

/**
     /users/<id | userPrincipalName>/photo/$value
 */

function getUserPhoto(accessToken, userId, callback) {
          var options = {
            host: 'graph.microsoft.com',
            path: "/v1.0/users/" +userId + "/photo/$value",
            method: 'GET',
            headers: {
              Authorization: 'Bearer ' + accessToken
            }
          };

          https.get(options, function (response) {
            response.setEncoding('binary'); /* This is very very necessary! */
            var body = '';
            response.on('data', function (d) {
              body += d;
            });
            response.on('end', function () {
              var error;
              if (response.statusCode === 200) {
                    /* save as "normal image" */
                fs.writeFile('./public/img/image.jpeg', body, 'binary',  function(err){
                    if (err) throw err
                    console.log('Image saved ok')
                })
                /* callback - for example show in template as base64 image */
                callback(new Buffer(body, 'binary').toString('base64'));
              } else {
                error = new Error();
                error.code = response.statusCode;
                error.message = response.statusMessage;
                // The error body sometimes includes an empty space
                // before the first character, remove it or it causes an error.
                body = body.trim();
                error.innerError = JSON.parse(body).error;
                callback(error, null);
              }
            });
          }).on('error', function (e) {
            callback(e, null);
          });
        }
1
votes

This is an older question but I hope this will be helpful to some (C#).

Catch the incoming array as a byteArray and convert it to a base64string. These can easily be converted to images or saved in DB's

    public static async void GetPhoto(HttpClient client, string id)
    {
        var resp = await client.GetAsync(@"https://graph.microsoft.com/v1.0/users/" + id + "/photos/240x240/$value");

        var buffer = await resp.Content.ReadAsByteArrayAsync();
        var byteArray = buffer.ToArray();

        string base64String = Convert.ToBase64String(byteArray);
        if(base64String != null && base64String != "")
        {
            //Insert into database or convert.
        }
    }
0
votes

TypeScript code to get the photo

  @observable private photo: string;

    getPhoto('/me/photos/48x48/$value').then((photo) => {
      this.photo = photo;
    }).catch(error => {});
  }

<img className='br24' src={this.photo}/>

export function getPhoto(query: string): Promise<string> {
  let promise = new Promise<string>((resolve, reject) => {
    adalContext.AuthContext.acquireToken("https://graph.microsoft.com", (error, token) => {
      if (error) {
        reject(error);
      } else {
        if (query.indexOf('/') != 0)
          query = '/' + query;
        let u = `https://graph.microsoft.com/v1.0${query}`;
        axios.get(u, { headers: { Authorization: `Bearer ${token}`, encoding: null }, responseType: 'arraybuffer' }).then(
          val => {
            let photo = 'data:' + val.headers['content-type'] + ';base64,' + new Buffer(val.data, 'binary').toString('base64');
            resolve(photo);
          },
          error => {
            reject(error);
          }
        );
      }
    });
  });

  return promise;
}

0
votes

Had the same issue all day!

Main points to consider

  • response.blob() Response.blob()
    *** The blob() method of the Response interface takes a Response stream and reads it to completion. It returns a promise that resolves with a Blob. ***
  • window.URL.createObjectURL(result) URL.createObjectURL()
    *** The new object URL represents the specified File object or Blob object. ***

When using a standard response such as Response.text() or Response.json() you will receive

SyntaxError: Unexpected token � in JSON at position 0

        fetch("https://graph.microsoft.com/v1.0/me/photo/$value", requestOptions)
          .then(response => response.blob())
          .then(result => setUserImage(window.URL.createObjectURL(result)))
          .catch(error => console.log('error', error));