Commonly Occurring Errors in Microsoft Graph Integrations and How To Troubleshoot Them (Part 5)

Microsoft Graph is a powerful tool that allows developers to access various Microsoft services, including OneDrive, SharePoint, Outlook, and more. One feature of Microsoft Graph that is particularly useful for productivity is the ability to read attachment content of To-Do task and event attachments. This allows users to access important information and files directly from their To-Do tasks and events, without having to switch between different applications. 

If you haven’t read the first parts of this series, here they are:

For both use cases below, I have used MS Graph Java SDK 5.42.0. 

Read MS To-Do Tasks Attachment Content Such as Pictures

It's quite easy to get the content bytes of the attachment. Just send a GET request to the following URL: 

HTML
 
https://graph.microsoft.com/v1.0/me/todo/lists/{list_id}/tasks/{task_id}/attachments/{attachment_id}/$value


Replace {list_id}, {task_id}, and {attachment_id} with the IDs of the list, task, and attachment that you want to retrieve. If you have a picture as an attachment, the response of the GET request would be the picture itself. If you remove the keyword $value, then the response looks like as in the following example: 

JSON
 
{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('...')/attachments/$entity",
    "@odata.type": "#microsoft.graph.taskFileAttachment",
    "contentBytes": "AAAAKGZ0eXBoZWljAAAAAG1pZjFNaUhFT ... ",
  	"id": "...",
    "name": "IMG_1022(1).HEIC",
    "size": 2281219,
    "lastModifiedDateTime": "2023-05-05T06:59:21Z",
    "contentType": "image/heic"
  
}


Hint: The attachment content is displayed as content bytes. 

How to read attachment content via the MS Graph Java SDK is shown in the next sample:

Java
 
String accessToken = "YOUR_ACCESS_TOKEN_HERE";

GraphServiceClient graphClient = GraphServiceClient
	.builder()
    .authenticationProvider(request -> {
        request.addHeader("Authorization", "Bearer " + accessToken);
    })
  	.buildClient();

String taskId = "TASK_ID_HERE";

List<Attachment> attachments = graphClient
	.me()
  	.tasks(taskId)
  	.attachments()
  	.buildRequest()
  	.get();

for (Attachment attachment : attachments) {
    InputStream attachmentStream = graphClient
      .me()
      .tasks(taskId)
      .attachments(attachment.id)
      .content()
      .buildRequest()
      .get();
    // Do something with the attachment stream
}


Use the getAttachments() method to get a list of attachments associated with the task. For each attachment, you can use the getContent() method to read the content of the attachment. Note that you should handle any exceptions that may occur during this process. Additionally, this code assumes that you have the necessary permissions to access the task and its attachments.

Read MS Event Attachment Content Such as Pictures

As the use case of To-Do tasks above, you can get the attachment content via a GET request:

HTML
 
GET /me/events/{event-id}/attachments/{attachment-id}/$value


By making a GET request to the events endpoint, including the event ID and attachment ID in the request URL, the response will include the raw binary content of the attachment. As before, you may need to include an access token or other authentication credentials in your API request. 

If you remove $value from the request, q.e., the response will include metadata about the attachment, such as its content type and size, in addition to the raw binary content as content bytes. Once you have obtained the attachment content, you can use it as needed in your application. For example, if the attachment is a picture, you can get the picture using the request below.

HTML
 
GET /me/events/{event-id}/attachments/{attachment-id}


Check out the next example of how to read attachment content via the MS Graph Java SDK for MS Events: 

Java
 
String accessToken = "YOUR_ACCESS_TOKEN_HERE";

GraphServiceClient graphClient = GraphServiceClient
	.builder()
    .authenticationProvider(request -> {
        request.addHeader("Authorization", "Bearer " + accessToken);
    })
  	.buildClient();

String eventId = "EVENT_ID_HERE";

List<Attachment> attachments = graphClient
	.me()
  	.events(eventId)
  	.attachments()
  	.buildRequest()
  	.get();

for (Attachment attachment : attachments) {
    InputStream attachmentStream = graphClient
      .me()
      .events(eventId)
      .attachments(attachment.id)
      .content()
      .buildRequest()
      .get();
    // Do something with the attachment stream
}


Similar to the use case of To-Do tasks, first, we have to authenticate ourselves and create a GraphServiceClient. Afterward, we use the getAttachments() method to get a list of attachments associated with the event. For each attachment, you can use the getContent() method to read the content of the attachment. Let me note: you should handle any exceptions that may occur during this process. Additionally, this code assumes that you have the necessary permissions to access the event and its attachments as we already have seen at To-Do tasks.

Read Content Bytes From Attachments Such as Pictures

Let's assume you have to process attachment content of To-Do tasks or events within your application and your application has no user interface and runs only in the background. Your attachment is a picture. In this case, you can't process the return value that you get from the requests:

HTML
 
/me/todo/lists/{list_id}/tasks/{task_id}/attachments/{attachment_id}/$value


Or 

HTML
 
 /me/events/{event-id}/attachments/{attachment-id}/$value


To get the content bytes of the picture, you can use the following requests for example:

HTTP
 
/me/events/{event-id}/attachments/{attachment-id}


Or

HTTP
 
/me/todo/lists/{list_id}/tasks/{task_id}/attachments/{attachment_id}


In case a resource type is an event, your response will look like this: 

JSON
 
{
  	"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('dfb74...D')/attachments/$entity",
    "@odata.type": "#microsoft.graph.fileAttachment",
    "@odata.mediaContentType": "image/heic",
    "id": "AAMkADg4ZTk4NTQ5LTEyMWYtNDg5OC1hZjcxLWMzZT ...",
  	"lastModifiedDateTime": "2023-05-05T07:46:39Z",
    "name": "IMG_1022.HEIC",
    "contentType": "image/heic",
    "size": 2281207,
    "isInline": false,
    "contentId": null,
    "contentLocation": null,
    "contentBytes": "AAAAKGZ0eXBoZWljAAAAAG1pZjFNaUh ..."
}


To optimize the response to avoid the other properties such as contentType, size, and so on, you can modify the request as follows: 

HTTP
 
https://graph.microsoft.com/v1.0/me/events/AAMkADg4ZTk4NTQ5LTEyMWYtNDg5OC1hZjcxLWMzZTh[…]NT93Oo=?$select=microsoft.graph.fileAttachment/contentBytes


Via the request parameter select, you only will get back the property contentBytes. Your response is supposed to look as follows:

JSON
 
{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('...ea5')/events('AAMk...A%3D')/attachments(microsoft.graph.fileAttachment/contentBytes)/$entity",
    "@odata.type": "#microsoft.graph.fileAttachment",
    "@odata.mediaContentType": "image/heic",
    "id": "AAMkADg4ZTk4NTQ5LTEyMWYtNDg5O ... ",
  	"contentBytes": "AAAAKGZ0eXBoZWljAAAAAG1pZjFNaUhFTWl ..."
}


Within the MS Graph Java SDK, we have seen in both use cases above, we get an object from object type Inputstream as return from the client graphClient

To get the byte array from the input stream you can use Google package com.google.common.io to write the byte array. The code line may look like the following:

Java
 
ByteStreams.toByteArray(getInputStreamOfAttachmentContent(userID, listID, taskID, attachmentID));
 


With the method:

Java
 
private InputStream getInputStreamOfAttachmentContent(userID, listID, taskID, attachmentID) {
        return getGraphService(user).getGraphServiceClient()
                .users(userID)
                .todo()
                .lists(listID)
                .tasks(taskID)
                .attachments(attachmentID)
                .content()
                .buildRequest()
                .get();
    }


Conclusion

We can see that in both use cases, the attachment content can be read very easily. Microsoft has implemented a very uniform way to read the attachment content for To-Do tasks and events. We do not have always consistency if we use the MS Graph APIs and SDKs. Take a look at the approach of reading attachment content of messages or uploading large attachments of To-Do tasks and events.

 

 

 

 

Top