Search code examples
pythonsharepointazure-ad-msalazure-ad-graph-api

Reading/Downloadind an excel file from my organization sharepoint with Python


I'm trying to read/download an excel file from a shared folder in my organization's sharepoint. At the moment, I have an Azure AD Application that I am trying to use to authenticate the access. I am using a code that I found here to test the connection and I am still getting the following error message:

None
{'token_type': 'Bearer', 'expires_in': 3599, 'ext_expires_in': 3599, 'access_token': 'retrieved_token'}
Read file failed. Status code: 400

My app has the following accesses: app API permissions

I also requested the office admin to approve the permssion from this link: https://login.microsoftonline.com/{tenant_ID_HERE}/adminconsent?client_id={CLIENT ID HERE} which I saw in another post that helped the OP, and he has approved.

Here's my code:

import requests
import msal
import io
import pandas as pd

# Azure App Parameters
client_id = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
client_secret = 'mysecrethere'
authority = 'https://login.microsoftonline.com/tenant_id'

# SharePoint Parameters
sharepoint_site_url = 'https://myorganization.sharepoint.com'
excel_file_path = '/teams/group/Shared Documents/folder1/folder2/folder3/myexcelfile.xlsx'

# Create a ConfidentialClientApplication instance for credentials
app = msal.ConfidentialClientApplication(client_id, authority=authority, client_credential=client_secret)

# Acquire an access token using client credentials
result = app.acquire_token_silent(scopes=['https://graph.microsoft.com/.default'], account=None)
print(result)
if not result:
    # If the token is not found in the cache, acquire a new one
    result = app.acquire_token_for_client(scopes=['https://graph.microsoft.com/.default'])

# Print the result to inspect its content
print(result)

if 'access_token' in result:
    # Successful
    access_token = result['access_token']
    
    # Call Microsoft Graph to read the Excel file
    graph_url = f'https://graph.microsoft.com/v1.0/sites/https://myorganization.sharepoint.com:/r/teams/group/Shared Documents/folder1/folder2/folder3/myexcelfile.xlsx:/content'
    headers = {'Authorization': f'Bearer {access_token}'}
    response = requests.get(graph_url, headers=headers)

    if response.status_code == 200:
        # Successful
        excel_data = io.BytesIO(response.content)
        df = pd.read_excel(excel_data)
        print(df.head())
    else:
        print(f"Read file failed. Status code: {response.status_code}")
else:
    print("Failed to get access token.")


Solution

  • I uploaded a file in SharePoint Site same as you like below:

    enter image description here

    The error "Read file failed. Status code: 400" usually occurs if you are passing the invalid Graph URL/query to perform the action.

    The URL must be the format https://graph.microsoft.com/v1.0/sites/SiteID/lists/listID/items/ItemID/driveItem/content

    Get the list ID:

    GET https://graph.microsoft.com/v1.0/sites/SiteID/lists
    

    enter image description here

    List items and note the ID:

    https://graph.microsoft.com/v1.0/sites/SiteID/lists/ListID/items
    

    enter image description here

    Modify the code by passing the correct Microsoft Graph query like below:

    import requests
    import msal
    import io
    import pandas as pd
    
    # Azure App Parameters
    client_id = 'a6ade814-fdba-4432-b71a-5af5ea***'
    client_secret = '1di8Q~2Mltdd1l8****"'
    authority = 'https://login.microsoftonline.com/TenantId'
    
    # SharePoint Parameters
    sharepoint_site_url = 'https://****.sharepoint.com'
    #excel_file_path = 'https://****.sharepoint.com/sites/testruk/folder1/Book.xlsx'
    # Create a ConfidentialClientApplication instance for credentials
    app = msal.ConfidentialClientApplication(client_id, authority=authority, client_credential=client_secret)
    
    # Acquire an access token using client credentials
    result = app.acquire_token_silent(scopes=['https://graph.microsoft.com/.default'], account=None)
    print(result)
    if not result:
        # If the token is not found in the cache, acquire a new one
        result = app.acquire_token_for_client(scopes=['https://graph.microsoft.com/.default'])
    
    # Print the result to inspect its content
    print(result)
    
    if 'access_token' in result:
        # Successful
        access_token = result['access_token']
        
        # Call Microsoft Graph to read the Excel file
        graph_url = f'https://graph.microsoft.com/v1.0/sites/siteid/lists/listid/items/10/driveItem/content'
        headers = {'Authorization': f'Bearer {access_token}'}
        response = requests.get(graph_url, headers=headers)
    
        if response.status_code == 200:
            # Successful
            excel_data = io.BytesIO(response.content)
            df = pd.read_excel(excel_data)
            print(df.head())
        else:
            print(f"Read file failed. Status code: {response.status_code}")
    else:
        print("Failed to get access token.")
    

    enter image description here

    You will get a @microsoft.graph.downloadUrl, when you click the URL, the file will get downloaded.

    Make sure to grant Admin consent to Sites.Read.All Microsoft Graph API permission:

    enter image description here

    Reference:

    postman - Downloading Sharepoint File using Microsoft Graph API not showing content attribute - Stack Overflow by Vadim Gremyachev