How to download OneDrive shared files from a Python application?

Bruno Villas Boas 0 Reputation points
2023-03-09T19:52:23.0833333+00:00

I'm trying to create a system that downloads shared files to the PC using python.

I have already tried different ways to do that, but until now I did not figure out how to log in to OneDrive with a user/pass and download the file.

From the Sharepoint API documentation, I'm seeing that I need to have a client-id with a client-secret for each 'SharePoint page' that I want to download a file. This is good when the application needs full (read or write) access to the Sharepoint page, but it's not good when a certain user wants to share only a single file inside its OneDrive.

For example, I have the following three links from different user spaces:

  • xpto.sharepoint.com/:u:/p/users_space/file1.txt
  • xpto.sharepoint.com/:u:/p/secondusersspace/file2.txt
  • abcd.sharepoint.com/:u:/p/other_usersspace/file3.txt

Using my current implementation, I need to register the application for each one of the spaces. Below is a snippet of my code:

client_id = '
OneDrive
OneDrive
A Microsoft file hosting and synchronization service.
1,142 questions
SharePoint
SharePoint
A group of Microsoft Products and technologies used for sharing and managing content, knowledge, and applications.
10,820 questions
SharePoint Development
SharePoint Development
SharePoint: A group of Microsoft Products and technologies used for sharing and managing content, knowledge, and applications.Development: The process of researching, productizing, and refining new or existing technologies.
3,042 questions
OneDrive Management
OneDrive Management
OneDrive: A Microsoft file hosting and synchronization service.Management: The act or process of organizing, handling, directing or controlling something.
1,272 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. RaytheonXie_MSFT 36,171 Reputation points Microsoft Vendor
    2023-03-10T01:45:20.8566667+00:00

    Hi @Bruno Villas Boas

    I will recommend you to use Office365-REST-Python-Client. You can download onedrive file with following code

    import os
    import tempfile
    
    from examples import acquire_token_by_username_password
    from office365.graph_client import GraphClient
    from office365.onedrive.driveitems.driveItem import DriveItem
    
    client = GraphClient(acquire_token_by_username_password)
    # address folder by path
    folder_item = client.me.drive.root.get_by_path("archive").get().execute_query()
    
    with tempfile.TemporaryDirectory() as local_path:
        items = folder_item.children.get().execute_query()
        for drive_item in items:  # type: DriveItem
            if drive_item.is_file:
                with open(os.path.join(local_path, drive_item.name), 'wb') as local_file:
                    drive_item.download(local_file).execute_query()  # download file content
                print("File '{0}' has been downloaded into {1}".format(drive_item.name, local_file.name))
    
    

    Here is the document for more details

    https://github.com/vgrem/Office365-REST-Python-Client/tree/master/examples/onedrive


    If the answer is helpful, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

  2. Bruno Villas Boas 0 Reputation points
    2023-03-10T16:57:12.5366667+00:00

    Hi RaytheonXie, thanks for your reply.

    During my research, I saw the link that you shared. To make it works, I think that I need access to the Azure AD, is that right? Cause looking at the path described in the documentation (Azure portal > Azure AD), the following page appears to me:
    User's image

    Ok, so I tried to use the second way to authenticate, with the code that you shared, and I got the following error:

    C:\Users\<user's folder>\codes\Office365-REST-Python-Client>py office_test.py
    Traceback (most recent call last):
      File "C:\Users\<user's folder>\codes\Office365-REST-Python-Client\office_test.py", line 4, in <module>
        from examples import acquire_token_by_username_password
      File "C:\Users\<user's folder>\codes\Office365-REST-Python-Client\examples\__init__.py", line 5, in <module>
        from tests import settings
      File "C:\Users\<user's folder>\codes\Office365-REST-Python-Client\tests\__init__.py", line 18, in <module>
        class SecEnvInterpolation(BasicInterpolation):
      File "C:\Users\<user's folder>\codes\Office365-REST-Python-Client\tests\__init__.py", line 19, in SecEnvInterpolation
        secure_vars = os.environ.get('office365_python_sdk_securevars').split(';')
    AttributeError: 'NoneType' object has no attribute 'split'
    

    I tried to change the settings.cfg file under /test folder but no success so far.

    EDIT:

    I finally got it working for the files inside my company's SharePoint using 'UserCredential' but I'm still not able to access shared files from others' Sharepoint.

    For example, my user has a site under "xpto.sharepoint.com" and, from the browser it has access to the file abcd.sharepoint.com/:u:/p/other_usersspace/file3.txt. But, even after retrieving the context from the site URL, the following error appears:

    <office365.sharepoint.client_context.ClientContext object at 0x000001F99427B0A0>
    An error occurred while retrieving auth cookies from https://abcd.sharepoint.com/_forms/default.aspx?wa=wsignin1.0
    Traceback (most recent call last):
      File "C:\Users\<user>\codes\Office365-REST-Python-Client\office_bruno.py", line 38, in <module>
        file = ctx.web.get_file_by_server_relative_url(file_url).download(local_file).execute_query()
      File "C:\Users\<user>\codes\Office365-REST-Python-Client\office365\runtime\client_object.py", line 44, in execute_query
        self.context.execute_query()
      File "C:\Users\<user>\codes\Office365-REST-Python-Client\office365\runtime\client_runtime_context.py", line 161, in execute_query
        self.pending_request().execute_query(qry)
      File "C:\Users\<user>\codes\Office365-REST-Python-Client\office365\runtime\client_request.py", line 57, in execute_query
        response = self.execute_request_direct(request)
      File "C:\Users\<user>\codes\Office365-REST-Python-Client\office365\runtime\client_request.py", line 69, in execute_request_direct
        self.beforeExecute.notify(request)
      File "C:\Users\<user>\codes\Office365-REST-Python-Client\office365\runtime\types\event_handler.py", line 21, in notify
        listener(*args, **kwargs)
      File "C:\Users\<user>\codes\Office365-REST-Python-Client\office365\sharepoint\client_context.py", line 212, in _authenticate_request
        self.authentication_context.authenticate_request(request)
      File "C:\Users\<user>\codes\Office365-REST-Python-Client\office365\runtime\auth\authentication_context.py", line 97, in authenticate_request
        self._provider.authenticate_request(request)
      File "C:\Users\<user>\codes\Office365-REST-Python-Client\office365\runtime\auth\providers\saml_token_provider.py", line 77, in authenticate_request
        self.ensure_authentication_cookie()
      File "C:\Users\<user>\codes\Office365-REST-Python-Client\office365\runtime\auth\providers\saml_token_provider.py", line 84, in ensure_authentication_cookie
        self._cached_auth_cookies = self.get_authentication_cookie()
      File "C:\Users\<user>\codes\Office365-REST-Python-Client\office365\runtime\auth\providers\saml_token_provider.py", line 100, in get_authentication_cookie
        return self._get_authentication_cookie(token, user_realm.IsFederated)
      File "C:\Users\<user>\codes\Office365-REST-Python-Client\office365\runtime\auth\providers\saml_token_provider.py", line 246, in _get_authentication_cookie
        raise ValueError(self.error)
    ValueError: An error occurred while retrieving auth cookies from https://abcd.sharepoint.com/_forms/default.aspx?wa=wsignin1.0
    

    The code that is working inside the company is something like the following and the error is happening :

    import os
    import tempfile
    
    from office365.sharepoint.client_context import ClientContext
    from office365.runtime.auth.user_credential import UserCredential
    
    user_credentials = UserCredential('<user>','<pass>')
    
    url = "https://abcd.sharepoint.com/personal/other_usersspace/file3.txt"
    
    file_url = "personal/other_usersspace/file3.txt"
    
    print(f'file_url: {file_url}')
    
    ctx = ClientContext(site_url).with_credentials(user_credentials)
    
    print(ctx)
    
    download_path = os.path.join(tempfile.mkdtemp(), os.path.basename(file_url))
    
    with open(download_path, "wb") as local_file:
        file = ctx.web.get_file_by_server_relative_url(file_url).download(local_file).execute_query()
    
    print("[Ok] file has been downloaded into: {0}".format(download_path))
    

    Thanks again.

    Bruno

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.