Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can i upload a file to sharepoint ? #40

Closed
attibalazs opened this issue Jul 14, 2017 · 10 comments
Closed

How can i upload a file to sharepoint ? #40

attibalazs opened this issue Jul 14, 2017 · 10 comments
Labels

Comments

@attibalazs
Copy link

attibalazs commented Jul 14, 2017

I am trying to upload a file to sharepoint, am I on the right path ?

def upload_file(ctx, listTitle, path):
    list_obj = ctx.web.lists.get_by_title(listTitle)
    folder = list_obj.root_folder
    ctx.load(folder)
    ctx.execute_query()

    files = folder.files
    with open(path, 'rb') as f:
        content = f.read()
        file_creation_information = FileCreationInformation()
        file_creation_information.overwrite = True
        file_creation_information.url = path
        file_creation_information.content = content
        file_new = files.add(file_creation_information)
@benpolinsky
Copy link

I've only used the ClientRequest class to do this.

   def upload_binary_file(self, file):
        """Attempt to upload a binary file to SharePoint"""

        folder_url = "folder_to_upload_to"
        text_file = basename(file.name)
        full_url = "{0}/_api/web/GetFolderByServerRelativeUrl('{1}')/Files/add(url='{2}', overwrite=true)".format(self.base_url, folder_url, text_file)
        options = RequestOptions(full_url)
        context = ClientContext(full_url, self.ctx_auth)
        options.set_header('Accept', 'application/json; odata=verbose')
        options.set_header('Content-Type', 'application/octet-stream')
        options.set_header('Content-Length', str(os.path.getsize(file.name)))
        options.set_header('X-RequestDigest', YOUR_FORM_DIGEST)
        options.method = 'POST'
        file_name = file.name        
        with open(file_name, 'rb') as outfile:
          
            # instead of executing the query directly, we'll try to go around
            # and set the json data explicitly
          
            context.authenticate_request(options)
          
            data = requests.post(url=full_url, data=outfile, headers=options.headers, auth=options.auth)
            if data.status_code == 200:
                # our file has uploaded successfully
                # let's return the URL
                base_site = data.json()['d']['Properties']['__deferred']['uri'].split("/sites")[0]
                relative_url = data.json()['d']['ServerRelativeUrl'].replace(' ', '%20')
                
                return base_site + relative_url
            else:
                return "Log Failed to Upload" 

@attibalazs
Copy link
Author

attibalazs commented Jul 20, 2017

@benpolinsky Thanks for posting the snippets i eventually got it working. I had trouble getting the form digest at first, but once i figured out how to do that it worked.

from office365.runtime.auth.authentication_context import AuthenticationContext
from office365.sharepoint.client_context import ClientContext
from office365.runtime.utilities.request_options import RequestOptions

from office365.sharepoint.file_creation_information import FileCreationInformation
from settings import settings
import requests
import os
from os.path import basename


ctx_auth = AuthenticationContext(url=settings['url'])
if ctx_auth.acquire_token_for_user(username=settings['username'], password=settings['password']):
    upload_binary_file("c:\temp\myfile.txt",ctx_auth)

def upload_binary_file(file_path, ctx_auth):
    """Attempt to upload a binary file to SharePoint"""

    base_url = settings['url']
    folder_url = "MyFolder"
    file_name = basename(file_path)
    files_url ="{0}/_api/web/GetFolderByServerRelativeUrl('{1}')/Files/add(url='{2}', overwrite=true)"
    full_url = files_url.format(base_url, folder_url, file_name)

    options = RequestOptions(settings['url'])
    context = ClientContext(settings['url'], ctx_auth)
    context.request_form_digest()

    options.set_header('Accept', 'application/json; odata=verbose')
    options.set_header('Content-Type', 'application/octet-stream')
    options.set_header('Content-Length', str(os.path.getsize(file_path)))
    options.set_header('X-RequestDigest', context.contextWebInformation.form_digest_value)
    options.method = 'POST'

    with open(file_path, 'rb') as outfile:

        # instead of executing the query directly, we'll try to go around
        # and set the json data explicitly

        context.authenticate_request(options)

        data = requests.post(url=full_url, data=outfile, headers=options.headers, auth=options.auth)

        if data.status_code == 200:
            # our file has uploaded successfully
            # let's return the URL
            base_site = data.json()['d']['Properties']['__deferred']['uri'].split("/sites")[0]
            relative_url = data.json()['d']['ServerRelativeUrl'].replace(' ', '%20')

            return base_site + relative_url
        else:
            return data.json()['error']

@saily
Copy link

saily commented Jul 28, 2017

I'd prefer to have a simple api to upload a file to sharepoint. This is way too complex.

@alibux
Copy link

alibux commented Jan 23, 2018

@attibalazs Thanks for the script. I did run into the following error and currently stuck here:

File "C:\Python27\lib\site-packages\office365\runtime\auth\saml_token_provider.py", line 65, in get_authentication_cookie
return 'FedAuth=' + self.FedAuth + '; rtFa=' + self.rtFa
TypeError: cannot concatenate 'str' and 'NoneType' objects

Did you also need to use a client id and client secret in addition to the SP Online url, username and password?

@joeltone
Copy link

joeltone commented Feb 13, 2018

Thanks for this @attibalazs . It worked great for me.

@coderrambo007
Copy link

I have doubt.. Does this code work for organisation accounts like myname@domain.mycompany.com or we need to have a proper office365 account like myname@mycompany.onmicrosoft.com ?

@DataExMachina
Copy link

DataExMachina commented Aug 28, 2018

Hi, I used @attibalazs script, which seems to work well until I try to upload data in Sharepoint :
data = requests.post(url=full_url, data=outfile, headers=options.headers, auth=options.auth)

I got 403 status. Is there something I should change in my office account config to get rights to write in Sharepoint in this way ?

@prasanta
Copy link

@attibalazs
use API. status = ctx_auth.acquire_token_for_app() instead of status=ctx_auth.acquire_token_for_user(username, password)
and install packge . pip install -U certifi

@pepejam
Copy link

pepejam commented Jul 4, 2019

Hello, I added some adjustments to your code that are working for me:

I am trying to upload a file to sharepoint, am I on the right path ?

def upload_file(ctx, listTitle, path):
    list_obj = ctx.web.lists.get_by_title(listTitle)
    folder = list_obj.root_folder
    ctx.load(folder)
    ctx.execute_query()

    files = folder.files
    ctx.load(files)
    ctx.execute_query()
with open(path, 'rb') as f:
    content = f.read()
    file_creation_information = FileCreationInformation()
    file_creation_information.overwrite = True
       file_creation_information.url = os.path.basename(path)
    file_creation_information.content = content
    file_new = files.add(file_creation_information)
       ctx.load(files)
       ctx.execute_query()

@vgrem vgrem added the question label Mar 13, 2020
@vgrem
Copy link
Owner

vgrem commented Mar 13, 2020

Greetings,

I propose to close this one since it has been answered.

To summarize:

the recommended way to upload a file into SharePoint library is demonstrated below:

#read a local file
path = "../tests/data/SharePoint User Guide.docx"
with open(path, 'rb') as content_file:
    file_content = content_file.read()

#upload it into Documents library
target_folder = context.web.lists.get_by_title("Documents").rootFolder
info = FileCreationInformation()
info.content = file_content
info.url = os.path.basename(path)
info.overwrite = True
target_file = target_folder.files.add(info)
context.execute_query()

But if file is larger than 2 MB then file needs to be uploaded as set of chunks:

ctx = ClientContext(site_url, ctx_auth)
size_1Mb = 1000000
local_path = "./data/big_buck_bunny.mp4"
target_url = "/Shared Documents"
result_file = ctx.web.get_folder_by_server_relative_url(target_url).files.create_upload_session(local_path, size_1Mb, print_upload_progress)
ctx.execute_query()
print('File {0} has been uploaded successfully'.format(result_file.properties['ServerRelativeUrl']))

where

def print_upload_progress(offset):
    print("Uploaded '{0}' bytes...".format(offset))

If you prefer to construct a upload request by yourself then the snippets provided by @attibalazs and @benpolinsky is a way to go.

Vadim

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

10 participants