Skip to content

Instantly share code, notes, and snippets.

@drmayu7
Forked from keathmilligan/msgraph-download.py
Created November 14, 2022 07:34
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drmayu7/459ae2cf9e07842f808235f1abf5ce25 to your computer and use it in GitHub Desktop.
Save drmayu7/459ae2cf9e07842f808235f1abf5ce25 to your computer and use it in GitHub Desktop.
Get info about and download a file from a SharePoint site with Microsoft Graph and MSAL
import requests
import msal
import atexit
import os.path
import urllib.parse
TENANT_ID = '<your tenant id>'
CLIENT_ID = '<your application id>'
SHAREPOINT_HOST_NAME = 'yourcompany.sharepoint.com'
SITE_NAME = '<your site name>'
AUTHORITY = 'https://login.microsoftonline.com/' + TENANT_ID
ENDPOINT = 'https://graph.microsoft.com/v1.0'
SCOPES = [
'Files.ReadWrite.All',
'Sites.ReadWrite.All',
'User.Read',
'User.ReadBasic.All'
]
cache = msal.SerializableTokenCache()
if os.path.exists('token_cache.bin'):
cache.deserialize(open('token_cache.bin', 'r').read())
atexit.register(lambda: open('token_cache.bin', 'w').write(cache.serialize()) if cache.has_state_changed else None)
app = msal.PublicClientApplication(CLIENT_ID, authority=AUTHORITY, token_cache=cache)
accounts = app.get_accounts()
result = None
if len(accounts) > 0:
result = app.acquire_token_silent(SCOPES, account=accounts[0])
if result is None:
flow = app.initiate_device_flow(scopes=SCOPES)
if 'user_code' not in flow:
raise Exception('Failed to create device flow')
print(flow['message'])
result = app.acquire_token_by_device_flow(flow)
if 'access_token' in result:
headers={'Authorization': 'Bearer ' + result['access_token']}
# get the site id
result = requests.get(f'{ENDPOINT}/sites/{SHAREPOINT_HOST_NAME}:/sites/{SITE_NAME}', headers=headers)
result.raise_for_status()
site_info = result.json()
site_id = site_info['id']
# get the drive id
result = requests.get(f'{ENDPOINT}/sites/{site_id}/drive', headers=headers)
result.raise_for_status()
drive_info = result.json()
drive_id = drive_info['id']
# download a file
file_path = 'General/Test Doc.docx' # replace this with the file you want to download
file_url = urllib.parse.quote(file_path)
result = requests.get(f'{ENDPOINT}/drives/{drive_id}/root:/{file_url}', headers=headers)
result.raise_for_status()
file_info = result.json()
file_id = file_info['id']
result = requests.get(f'{ENDPOINT}/drives/{drive_id}/items/{file_id}/content', headers=headers)
result.raise_for_status()
open(file_info['name'], 'wb').write(result.content)
else:
raise Exception('no access token in result')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment