Skip to content

Instantly share code, notes, and snippets.

@drmayu7
Forked from keathmilligan/msgraph-upload.py
Created November 14, 2022 07:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drmayu7/86bf5951329f42df49e67dcd10575d33 to your computer and use it in GitHub Desktop.
Save drmayu7/86bf5951329f42df49e67dcd10575d33 to your computer and use it in GitHub Desktop.
Upload a small file to a SharePoint site using MS Graph and MSAL
import requests
import msal
import atexit
import os.path
import urllib.parse
TENANT_ID = '<your tenant id>'
CLIENT_ID = '<your client id>'
SHAREPOINT_HOST_NAME = 'yourcompany.sharepoint.com'
SITE_NAME = '<your site>'
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:
access_token = result['access_token']
headers={'Authorization': 'Bearer ' + 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']
# upload a file to the 'General' folder -- replace these
filename = 'Small File.txt'
folder_path = 'General'
# check to see if file exists
path_url = urllib.parse.quote(f'{folder_path}/{filename}')
result = requests.get(f'{ENDPOINT}/drives/{drive_id}/root:/{path_url}', headers=headers)
if result.status_code == 200:
# file exists, replace its contents
file_info = result.json()
file_id = file_info['id']
result = requests.put(
f'{ENDPOINT}/drives/{drive_id}/items/{file_id}/content',
headers={
'Authorization': 'Bearer ' + access_token,
'Content-type': 'application/binary'
},
data=open(filename, 'rb').read()
)
elif result.status_code == 404:
# file does not exist, create a new item
folder_url = urllib.parse.quote(folder_path)
result = requests.get(f'{ENDPOINT}/drives/{drive_id}/root:/{folder_url}', headers=headers)
result.raise_for_status()
folder_info = result.json()
folder_id = folder_info['id']
file_url = urllib.parse.quote(filename)
result = requests.put(
f'{ENDPOINT}/drives/{drive_id}/items/{folder_id}:/{file_url}:/content',
headers={
'Authorization': 'Bearer ' + access_token,
'Content-type': 'application/binary'
},
data=open(filename, 'rb').read()
)
result.raise_for_status()
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