7

I have a Python script that saves a file to a server shared folder for a user to access. Our organization recently moved our server file structure to Sharepoint... including all the folders. (I've read multiple articles that's a bad idea, but there's no changing it right now.)

I have new code that uploads a file to the root folder of the Sharepoint library:

import sharepy s = sharepy.connect("site.sharepoint.com", "username", "password") r = s.post("https://site.sharepoint.com/_api/web/Lists/GetByTitle('Documents')/RootFolder/files\ /add(overwrite=true,url='test.csv')", \ "testing,foo,bar") print(r)

Is there a way to upload the file to a subfolder instead of the root? If so, how?

4
  • An option that may serve as an interim solution but does not directly upload to SharePoint is to sync a local folder with SharePoint and to have your python script copy the file to the local folder. So long as you are logged in to support the sync, your file will be uploaded to SharePoint and available for others. Commented May 4, 2020 at 23:24
  • 1
    That is true. I have several interim solutions available, but am now working on a preferred solution. Thank you! Commented May 6, 2020 at 14:18
  • You're welcome. I'm interested in the solution. Mine is complicated by the use of 2-factor authentication which, once entered, is remembered to allow the sync approach to work. I'll revisit this later when it bumps up in priority. Good luck. Commented May 6, 2020 at 15:39
  • Thankfully I'm not dealing with 2-factor authentication. My solution below. Good luck! Commented May 7, 2020 at 17:00

5 Answers 5

6

In case it helps anybody, here's my final code. It successfully posts a file to a sharepoint site team site library subfolder. Replace the italics with your information.

import sharepy 

s = sharepy.connect("*MySite*.sharepoint.com", "*username*", "*password*") 

r = s.post("https://*MySite*.sharepoint.com/sites/*TeamSiteName*/_api/web/GetFolderByServerRelativeUrl('/sites/*TeamSiteName*/Shared Documents/*FolderName*')/Files/" + "add(overwrite=true,url='test.csv')", "testing,foo,bar")

print r
Sign up to request clarification or add additional context in comments.

Comments

3

I've worked on the same problem some time back. Below is my code.

import requests
from shareplum import Office365

username = "YourUsername"
password = "YourPassword"
site_name = "Sitename"
doc_library = "SubfolderName"
base_path = "https://domainName.sharepoint.com"

file_name = "FileName"

# Obtain auth cookie
authcookie = Office365(base_path, username=username, password=password).GetCookies()
session = requests.Session()
session.cookies = authcookie
session.headers.update({'user-agent': 'python_bite/v1'})
session.headers.update({'accept': 'application/json;odata=verbose'})

# dirty workaround.... I'm getting the X-RequestDigest from the first failed call
session.headers.update({'X-RequestDigest': 'FormDigestValue'})
response = session.post( url=base_path + "/sites/" + site_name + "/_api/web/GetFolderByServerRelativeUrl('" + doc_library + "')/Files/add(url='a.txt',overwrite=true)",
                         data="")
session.headers.update({'X-RequestDigest': response.headers['X-RequestDigest']})

dest =  base_path + "/sites/" + site_name + "/_api/web/GetFolderByServerRelativeUrl('" + doc_library + "')/Files/add(url='a.txt',overwrite=true)" #session.post( url=base_path + "/sites/" + site_name + "/_api/web/GetFolderByServerRelativeUrl('" + doc_library + "')/Files/add(url='a.txt',overwrite=true)",data="")
print('Folder!')
# perform the actual upload
with open( file_name, 'rb') as file_input:
    try:
        print('uploading')
        response = session.post( 
            url=base_path + "/sites/" + site_name + "/_api/web/GetFolderByServerRelativeUrl('" + doc_library + "')/Files/add(url='" 
            + file_name + "',overwrite=true)",
            data=file_input)
    except Exception as err: 
        print("Some error occurred: " + str(err))
print('Uploaded successfully!')

Comments

1

Below is the code I used to upload files from Azure Blob storage to a new sub folder on Sharepoint using python in Databricks.

def upload_sharepoint(sp_filepath,blob_file_path):
  from office365.runtime.auth.authentication_context import AuthenticationContext
  from office365.sharepoint.client_context import ClientContext
  from office365.sharepoint.files.file import File
  import os
  
  url='https://<domain>.sharepoint.com/sites/<site1>/<subsite1>'
  username = 'user'
  pwd = 'password'

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

  blobpath = '/dbfs' + blob_file_path
  filename=os.path.basename(blob_file_path)
  
  #read content of file
  with open(blobpath, 'rb') as content_file:
    file_content = content_file.read()
  
  target_url = sp_filepath  # sharepoint url to upload a file 
  target_folder=ctx.web.get_folder_by_server_relative_url(target_url)
  try:
    folder_exist=ctx.load(target_folder).execute_query().properties['Exists']
  except Exception as e:
    folder_exist=False
    print('Folder Not Found,Creating Folder')
    
  if !folder_exist:
    try:
      target_folder = ctx.web.folders.add(target_url).execute_query()    #Create the folder, can create folder upto 1 level only
    except Exception as e:
      print('Parent folder Not Found',e)
  target_folder.upload_file(filename, file_content).execute_query()    # upload the file
  print('Uploaded '+filename+' to '+target_url)

The above code can be used to create a 1 level sub-folder within a folder that already exist.

For Ex, here we will create a folder name 'NewFolder' inside 'Pay file' folder that exist on Sharepoint:

sharepoint_fp='/sites/<site1>/<subsite1>/Document%20upload/Pay%20file/NewFolder' 
blob_path='/mnt/PayFile/'  
files=spark.createDataFrame(dbutils.fs.ls(blob_path))
files=files.select('name').collect()
for f in files:
  upload_sharepoint(sharepoint_fp,blob_path+f.name)

2 Comments

When I try to upload a pandas dataframe I get the following error: "Object of type DataFrame is not JSON serializable". Do you know maybe why?
@FedericoGentile You cant upload a dataframe to sharepoint folder, first you have to write it to a csv or excel file and then that file you can upload.
0

Yes you can upload files to sub-folder via rest api. Please take a reference of following endpoints:

And below are some demos about how to upload files using python (but they might not use the same library as yours).

/////// Update ////// enter image description here

3 Comments

I modified my code based on your "create a file and add it to a folder" link above. import sharepy s = sharepy.connect("site.sharepoint.com", "username", "password") r = s.post("williamsburghealthfoundati.sharepoint.com/sites/ValerieTest/…\ GetFolderByServerRelativeUrl('/Folder1')/Files/\ add(overwrite=true,url='test.csv')", "testing,foo,bar") print(r) I added a specific site name and incorporated the GetFolderByServerRelativeUrl call. The result is Response [400]. Thank you!
400 is bad request. Generally it means the URL is not correct.
Thank you! I knew my URL was incorrect but couldn't find the write combination. I had to repeat the sites/TeamSiteName piece in the URL and the GetFolderByServerRelativeUrl.
0

After so many tries, I finally made this work with less line coding than I expected.

I was having some issues with the some urls and folder paths that's why I put the "r" to get the raw path.

from shareplum import Site from shareplum import Office365 from shareplum.site import Version

Normal authentication

authcookie = Office365(r'https://.sharepoint.com', username='@', password='***').GetCookies()

Here you fill the info from your site

site = Site(r'https://*******.sharepoint.com/sites/sitename/',version=Version.v365, authcookie=authcookie)

And here you just fill the info of your folder

folder = site.Folder('Shared Documents/Your Folder')

Source: https://shareplum.readthedocs.io/en/latest/files.html#folders

Encoding and Errors are optional

with open(r'C:/Users/Alessandro.paiva/Desktop/file.xlsx', encoding = 'latin-1', errors = 'ignore') as file: fileContent = file.read()

Name of the file

folder.upload_file(fileContent, r'file.xlsx')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.