25

I have a requirement of downloading and uploading the files to Sharepoint sites. This has to be done using python. My site will be as https://ourOrganizationName.sharepoint.com/Followed by Further links Initially I thought I could do this using Request, BeautifulSoup etc., But I am not at all able to go to "Inspect Element" on the body of the site.

I have tried libraries such as Sharepoint,HttpNtlmAuth,office365 etc., but I am not successful. It always returning 403.

I tried google as much I can but again not successful. Even Youtube hasn't helped me.

Could anyone help me how to do that? Suggestion on Libraries with documentation link is really appreciated.

Thanks

DKS
  • 321
  • 1
  • 5
  • 9
  • 1
    Have you looked into the requests library? – JGerulskis Dec 07 '18 at 14:33
  • 3
    403 error is thrown due to authentication error. You should check if you have an access to this site and if you are providing auth data in requests. – Konrad Dec 07 '18 at 14:33
  • Can you please provide a link to a working SharePoint site? Maybe we can work backwards from the structure of the page we expect. – Nick Settje Dec 07 '18 at 14:35
  • I have tried requests library as well.. but not worked... The requirement is to upload the file to the sharepoint in the backend so that it will be available for the web users. Do we have documentation for python library sharepoint? – DKS Dec 07 '18 at 17:31

3 Answers3

35

Have you tried Office365-REST-Python-Client library, it supports SharePoint Online authentication and allows to download/upload a file as demonstrated below:

Download a file

from office365.runtime.auth.authentication_context import AuthenticationContext
from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.files.file import File

ctx_auth = AuthenticationContext(url)
ctx_auth.acquire_token_for_user(username, password)   
ctx = ClientContext(url, ctx_auth)
response = File.open_binary(ctx, "/Shared Documents/User Guide.docx")
with open("./User Guide.docx", "wb") as local_file:
    local_file.write(response.content)

Upload a file

ctx_auth = AuthenticationContext(url)
ctx_auth.acquire_token_for_user(username, password)   
ctx = ClientContext(url, ctx_auth)

path = "./User Guide.docx" #local path
with open(path, 'rb') as content_file:
   file_content = content_file.read()
target_url = "/Shared Documents/{0}".format(os.path.basename(path))  # target url of a file 
File.save_binary(ctx, target_url, file_content) # upload a file

Usage

Install the latest version (from GitHub):

pip install git+https://github.com/vgrem/Office365-REST-Python-Client.git

Refer /examples/shrepoint/files/* for a more details

Nuno André
  • 4,739
  • 1
  • 33
  • 46
Vadim Gremyachev
  • 57,952
  • 20
  • 129
  • 193
  • @VadimGremyachev - the link you provided is empty – kensai Sep 11 '19 at 13:12
  • 2
    Still not working ::-)) but I found it https://github.com/vgrem/Office365-REST-Python-Client/blob/master/examples/sharepoint/file_operations.py – kensai Sep 12 '19 at 14:14
  • SSL Errors on the install from git, use instead: pip install Office365-REST-Python-Client – DonkeyKong Jun 19 '20 at 15:01
  • 3
    It won't let me edit the answer, since the user isn't accepting edits. Here are the imports to get this working: from office365.runtime.auth.authentication_context import AuthenticationContext from office365.sharepoint.client_context import ClientContext from office365.sharepoint.file import File – Zach Aug 28 '20 at 17:51
  • Does this work if the O365 account is MFA protected? – Rajesh Swarnkar Sep 30 '22 at 05:46
1

You can also try this solution to upload file. For me, first solution to upload doesn't work.
First step: pip3 install Office365-REST-Python-Client==2.3.11

import os
from office365.sharepoint.client_context import ClientContext
from office365.runtime.auth.user_credential import UserCredential

def print_upload_progress(offset):
    print("Uploaded '{0}' bytes from '{1}'...[{2}%]".format(offset, file_size, round(offset / file_size * 100, 2)))


# Load file to upload:
path = './' + filename # if file to upload is in the same directory
try:
    with open(path, 'rb') as content_file:
        file_content = content_file.read()
except Exception as e:
    print(e)

file_size = os.path.getsize(path)

site_url = "https://YOURDOMAIN.sharepoint.com"
user_credentials = UserCredential('user_login', 'user_password') # this user must login to space

ctx = ClientContext(site_url).with_credentials(user_credentials)

size_chunk = 1000000
target_url = "/sites/folder1/folder2/folder3/"
target_folder = ctx.web.get_folder_by_server_relative_url(target_url)


# Upload file to SharePoint:
try:
    uploaded_file = target_folder.files.create_upload_session(path, size_chunk, print_upload_progress).execute_query()
    print('File {0} has been uploaded successfully'.format(uploaded_file.serverRelativeUrl))
except Exception as e:
    print("Error while uploading to SharePoint:\n", e)

Based on: https://github.com/vgrem/Office365-REST-Python-Client/blob/e2b089e7a9cf9a288204ce152cd3565497f77215/examples/sharepoint/files/upload_large_file.py

michal1298
  • 11
  • 2
0

This is how you do it, if you have public sharepoint url (no auth)

import requests, mimetypes

# Specify file sharepoint URL
file_url = 'https://organisarion-my.sharepoint.com/:b:/p/user1/Eej3XCFj7N1AqErjlxrzebgBO7NJMV797ClDPuKkBEi6zg?e=dJf2tJ'

# Specify desination filename
save_path = 'file'

# Make GET request with allow_redirect
res = requests.get(file_url, allow_redirects=True)

if res.status_code == 200:
    # Get redirect url & cookies for using in next request
    new_url = res.url
    cookies = res.cookies.get_dict()
    for r in res.history:
        cookies.update(r.cookies.get_dict())
    
    # Do some magic on redirect url
    new_url = new_url.replace("onedrive.aspx","download.aspx").replace("?id=","?SourceUrl=")

    # Make new redirect request
    response = requests.get(new_url, cookies=cookies)

    if response.status_code == 200:
        content_type = response.headers.get('Content-Type')
        print(content_type)
        file_extension = mimetypes.guess_extension(content_type)
        print(response.content)
        if file_extension:
            destination_with_extension = f"{save_path}{file_extension}"
        else:
            destination_with_extension = save_path

        with open(destination_with_extension, 'wb') as file:
            for chunk in response.iter_content(1024):
                file.write(chunk)
        print("File downloaded successfully!")
    else:
        print("Failed to download the file.")
        print(response.status_code)

A short explanation would be to GET the cookies & redirect url, use these cookies for making new GET request

sumitkanoje
  • 1,217
  • 14
  • 22