Image for post
Image for post
Background Photo by Annie Spratt on Unsplash, Icons Microsoft

Convert files to PDF using Microsoft Graph & Azure Functions

Philipp Bauknecht
May 1 · 8 min read

I do come across the task of creating PDF documents quite frequently and while there are a ton of open source and proprietary PDF libraries for almost any platform I was asking myself: Isn’t there a simpler way of doing this? Without caring about the drawbacks of the free libs or the cost and licensing complexity of the proprietary ones? Do I really want to care about all the settings and paging challenges?

In the age of serverless there has to be a better way! After some research I found out that this is basically a built in feature of OneDrive and Sharepoint Online as part of Office 365. Now I needed an API to actually use this as part of my app and there comes Microsoft Graph to the rescue!

“Microsoft Graph provides a unified programmability model that you can use to build apps for organizations and consumers that interact with the data of millions of users. You can use the Microsoft Graph REST APIs to access data in Azure Active Directory, Office 365 services, Enterprise Mobility and Security services, Windows 10 services, Dynamics 365, and more. Explore our documentation to learn more about how to use Microsoft Graph APIs.”
https://docs.microsoft.com/en-us/graph/

The beta version of the Microsoft Graph supports converting files through the DriveItem resource in the formats of doc, docx, epub, eml, htm, html, md, msg, odp, ods, odt, pps, ppsx, ppt, pptx, rtf, tif, tiff, xls, xlsm, xlsx to PDF (You can also convert pretty much any image format to jpg btw.).
More here: https://docs.microsoft.com/en-us/graph/api/driveitem-get-content-format?view=graph-rest-beta&tabs=http
In order to use the DriveItem resource you need either OneDrive or SharePoint Online as part of Office 365.

So let’s build a serverless app to give us an easy restful endpoint to convert files to PDF using the Microsoft Graph in the background. I will do this with C# and Azure Functions but of course this will work with any language and framework as long as it’s able to make http requests.

We will have to perform the following steps create this solution:

  1. Create a new Azure Functions app
  2. Create an OAuth2 authentication service to request an access token to call the Microsoft Graph
  3. Create a File Service to upload, convert and delete files using the Microsoft Graph
  4. Setup Dependency Injection
  5. Create a new function
  6. Upload the input file to a drive
  7. Download the file in pdf format
  8. Delete the input file from the drive

You can find the full code sample here: https://github.com/GrillPhil/ServerlessPDFConversionDemo

So let’s get started!

Prerequisites

Step 1: Create a new Azure Functions app

Open Visual Studio and create new Azure Function project. Make sure Azure Functions v3 (.NET Core) is selected and pick the Empty template.

Image for post
Image for post
Azure Function template selection dialog

Step 2: Create an OAuth2 authentication service to request an access token to call the Microsoft Graph

Before we can talk to the Microsoft Graph we need to authenticate and acquire an access token using OAuth 2 credential flow. In our case we have no signed in user present instead we want to authenticate as a service. Therefore we will use the credential flow providing a ClientId and ClientSecret of an app registration in AzureAD.

So let’s start by creating the app registration in Azure AD. Go to https://portal.azure.com and sign in with a admin user of your O365 tenant, go to Azure Active Directory and select App Registrations

Add a new app registration, pick a name e.g. PdfConversionService. Account types and Redirect URI are not relevant for this authentication mode, so you can just leave those as they are.

Image for post
Image for post

Next we need to save the values of Application (client) Id and Directory (tenant) Id for later use in our function’s settings from here:

Image for post
Image for post

Next we need to create a Client Secret as credential for our service to authenticate. Therefore select Certificates & Secrets in the left menu and click the New Client Secret button. Pick a description and Expiration:

Image for post
Image for post

Also save the Client Secret for later use in our function’s settings.

Finally we need to add permission to read and write in our SharePoint for the app registration. Select API permissions and click the Add a permission button. Choose Microsoft Graph and pick Application permission. Application permission means that we act in the name of an application instead on behalt of a user (delegated permission). Search for file and select Files.ReadWrite.All:

Image for post
Image for post

After adding the permission we also need to grant this permission to the app registration. The button here for might take a moment to become active. When active click it and enter your credentials in the popup window:

Image for post
Image for post

Now we have completed the app registration configuration.

To use the credentials we have just created along with some additional authentication configuration let’s create a model for authentication options:

And of course we need to provide these options in our local.settings.json for local debugging:

The authentication service will use those settings to request an access token that we can pass along with the request to the Microsoft Graph later. This can be done by a simple http request:

Step 3: Create a File Service to upload, convert and delete files using the Microsoft Graph

For our file operations we need to provide 2 options to a file service:

  • the Graph Endpoint to use and
  • the SiteId to upload and convert to files to

So like with authentication let’s start by defining an options model:

Before we can upload anything to SharePoint we need to create a new SharePoint site and get it’s id. So let’s create a new SharePoint site e.g. PDFDemo in the portal (https://portal.office.com → SharePoint).

Getting the id of a SharePoint site is actually a bit tricky as I have yet to find a place in SharePoint where it’s actually shown. My trick of getting it is using the Microsoft Graph Explorer (https://developer.microsoft.com/en-us/graph/graph-explorer), log in with the O365 admin account and calling this url: https://graph.microsoft.com/v1.0/sites/YOUR_SHAREPOINT_URL/:/sites/NAME_OF_SITE/?$select=id where YOUR_SHAREPOINT_URL is something like medialessondev.sharepoint.com. This will return a response like this:

So let’s add the full value of the id along with the Graph endpoint to our local.settings.json:

The file service will provide 3 methods:

  • Upload a file to SharePoint
  • Convert the file to pdf
  • Delete the original file in SharePoint

The file service will use the authentication service to acquire an access token a use it for all 3 requests to the Microsoft Graph. So let’s pass the authentication service and the options in through the constructor and write a helper method to create a HttpClient that uses the access token:

Let’s add a new method to upload a file to our SharePoint site:

Please note:

  • I’m using the library MediaTypeMap.core to get the correct file extension by the file’s content type
  • It’s important to also specify the file’s content type in the request header
  • We just need to return the id of the saved file in SharePoint in order to work with this file in the following methods

Next we need to implement a method to convert this file to pdf and retrieve it from SharePoint. This can be done in a single Graph request providing the path, fileId and target format:

Finally we also need a method to delete the original file in SharePoint once we have successfully converted it:

Step 4: Setup Dependency Injection

In order to use the 2 services we just created along with their options we need to create them somewhere. This is where dependency injection comes in handy. To use dependency injection in Azure Function app we need to add the package Microsoft.Azure.Functions.Extensions to our app using Nuget.

With this package we can now configure our services and options in a startup class:

Step 5: Create a new function

Add a new function to your project and name it ConvertToPdf. Select the Http trigger so our function can be called via a http request and pick Authorization level Anonymous so we don’t need to provide any credentials when calling this function.

Image for post
Image for post
Function configuration dialog

In order to use dependency injection in this function the class and method need to be NON static. Also we need to inject the file service and the pdf options into the constructor and save them into readonly fields:

Step 6: Upload the input file to a drive

With all services and settings and plumbing in place we can upload the file we receive in the function method using our file service:

Please note how the path variable is composed to point to the root folder of the SharePoint site.

Step 7: Download the file in pdf format

Next step is to download the pdf converted version of the file we just uploaded using the file id:

Step 8: Delete the original file from the drive and return the pdf

Almost there! Before returning the converted pdf file to the caller of the function let’s clean up by deleting the original file from SharePoint:

We made it!

Summary

This was a long post but I hope you still enjoyed it. I think this is a pretty convenient way of converting files to pdf in case you are in a scenario where you already have Office 365. The Azure AD authentication part is some work but can be reused in many ways when interaction with the Microsoft Graph. Doing this in Azure Functions lets me provide this functionality as a micro service to existing business processes and is free for up to 1 million requests per month.

medialesson

We help our customers design, architect, develop and…

Philipp Bauknecht

Written by

CEO @ medialesson. Microsoft Regional Director & MVP Windows Development. Father of identical twins. Passionate about great User Interfaces, NYC & Steaks

medialesson

We help our customers design, architect, develop and operate modern, intelligent, beautiful and usable apps on any platform powered by the Cloud, IoT and AI.

Philipp Bauknecht

Written by

CEO @ medialesson. Microsoft Regional Director & MVP Windows Development. Father of identical twins. Passionate about great User Interfaces, NYC & Steaks

medialesson

We help our customers design, architect, develop and operate modern, intelligent, beautiful and usable apps on any platform powered by the Cloud, IoT and AI.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store