PowerShell Script Example: Upload Small Files to SharePoint via Microsoft Graph

Learn how you can upload small files (up to 250 MB) to SharePoint Online with Microsoft Graph and PowerShell.

Lacking Documentation

I recently wanted to upload a couple of files to SharePoint Online using Microsoft Graph. It took me a while to figure it out so I thought that sharing my working script examples will probably help other people accomplish this task faster.

The documentation for uploading files with Microsoft Graph can be found here. The problem is that Microsoft Learn only lists an example for a web request and doesn’t really include any examples as to what the Body of the request needs to contain.

Example as of 2024-04-13

This is all we get today:

1
2
3
4
PUT https://graph.microsoft.com/v1.0/me/drive/root:/FolderA/FileB.txt:/content
Content-Type: text/plain

The contents of the file goes here.

While there is an example of how to update an existing file using Set-MgDriveItemContent it doesn’t mention how to construct the $params either:

1
2
3
4
5
Import-Module Microsoft.Graph.Files

$params = The contents of the file goes here.

Set-MgDriveItemContent -DriveId $driveId -DriveItemId $driveItemId -BodyParameter $params

Script Examples

Through trial and error, I discovered two different ways of uploading files to SharePoint Online through Microsoft Graph. One uses a simple web request using Invoke-RestMethod and app authentication and the other one uses the Invoke-GraphRequest Cmdlet from the Microsoft.Graph.Authentication module. The second one uses delegated permissions.

As it’s often the case with Graph operations, you first need to know some specific Ids before you can make your request. In this case, we need to know the Id of the drive in SharePoint. The DriveId is the Id of the Document Library. However, to get the DriveId, we also need to know the Id of the SharePoint Site. Therefore we must first find the SiteId, and then the DriveId. Unfortunately, the examples on the Graph documentation always assume that we already know these Ids so we need to get this data on our own…

Example Using Delegated Auth and Invoke-GraphRequest

Let’s look at the script using the Graph PowerShell module first. The first thing you want to do is to replace $siteName with the name of your destination site. When you run the script, you’ll be prompted to sign into Microsoft Graph. Make sure that you’ve previously configured and consented the delegated permissions Sites.Read.All and Files.ReadWrite.All to the Microsoft Graph Command Line Tools Enterprise Application or that you’re using your own App which has at least these two permissions configured.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$siteName = "Azure Automation"

Connect-MgGraph

# Site
$site = Get-MgSite -Search $siteName
$siteId = $site.id

# Drives
$drives = Get-MgSiteDrive -SiteId $siteId -All
$drive = $drives | Where-Object { $_.Name -eq "Documents" -or $_.Name -eq "Dokumente" }

# SharePoint Drive Id (Document Library)
$driveId = $drive.id

# File to upload
$filePath = "C:\Temp\Test.txt"
$fileProperties = Get-ChildItem -Path $filePath

# Read the file content as a byte array
$fileContent = [System.IO.File]::ReadAllBytes($filePath)

# Destination file name
$destinationName = "$($fileProperties.BaseName)-$(Get-Date -Format "yyyy-MM-dd HH-mm-ss").$($fileProperties.Extension)"

# Upload the file to SharePoint
Invoke-GraphRequest -Method PUT -Uri "https://graph.microsoft.com/v1.0/drives/$driveId/root:/Test/$destinationName`:/content" -Body $fileContent -ContentType "application/octet-stream" -Headers $Header

This will upload files up to 250 MB to SharePoint Online. If you rather want to use application authentication and not have any dependencies on installed Graph modules, you can do the same using HTTP requests.

Example Using App Auth and Invoke-RestMethod

The required permissions stay the same as for the first example. However, in this case they need to be application permissions. This script uses an external function to acquire a token which is then used to perform the web requests to the Graph API. The easiest way is to just clone the entire repository. This will keep the relative paths working. Alternatively, you can download the function from here and either copy it into the script or adjust the relative path. At this point, I’d like to thank Alex Asplund again for providing this awesome function to acquire a token for Microsoft Graph. I use his function in quite a lot in my scripts.

Before you run the script, fill in your own data for $TenantId, $AppId, $AppSecret and $SiteName.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$TenantId = ""
$AppId = ""
$AppSecret = ""
$SiteName = "Azure Automation"

. .\Functions\Connect-MgGraphHTTP.ps1

. Connect-MgGraphHTTP -TenantId $TenantId -AppId $AppId -AppSecret $AppSecret

# Site
$site = Invoke-RestMethod -Method Get -Headers $Header -Uri "https://graph.microsoft.com/v1.0/sites?search=$siteName"
$siteId = $site.value.id

# Drives
$drives = Invoke-RestMethod -Method Get -Headers $Header -Uri "https://graph.microsoft.com/v1.0/sites/$siteId/drives"

# SharePoint Drive Id (Document Library)
$driveId = ($drives.value | Where-Object { $_.Name -eq "Documents" -or $_.Name -eq "Dokumente" }).Id

# File to upload
$filePath = "C:\Temp\Test.txt"
$fileProperties = Get-ChildItem -Path $filePath

# Read the file content as a byte array
$fileContent = [System.IO.File]::ReadAllBytes($filePath)

# Destination file name
$destinationName = "$($fileProperties.BaseName)-$(Get-Date -Format "yyyy-MM-dd HH-mm-ss").$($fileProperties.Extension)"

# Upload the file to SharePoint
Invoke-RestMethod -Method PUT -Uri "https://graph.microsoft.com/v1.0/drives/$driveId/root:/Test/$destinationName`:/content" -Body $fileContent -ContentType "application/octet-stream" -Headers $Header

This code will give you the exact same result as the first script does but it will only use out-of-the-box PowerShell commands and doesn’t have any dependencies on PowerShell modules.

Summary

I hope you like these two examples on how to upload small files to SharePoint Online using Microsoft Graph. I think this can be a really powerful tool, especially when you pair it with your own Entra ID App Registration/Enterprise Application. When you create your own app to connect to Microsoft Graph, you can limit the use of it to a specific subset of users, such as IT staff and the app is only allowed to read all sites and read/write all files the signed in user has access to.

I’m thinking of scenarios where IT runs a diagnostic script or any other script that collects information on a users device and then uploads the log files/collected data directly to the specified SharePoint Site.

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Hosted on GitHub Pages
Built with Hugo
Theme Stack designed by Jimmy