I am trying to use the Office365-REST module to upload a file to Sharepoint.
from office365.runtime.auth.authentication_context import AuthenticationContext
from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.files.creation_information import FileCreationInformation
import traceback
try:
fullurl = 'https://org.sharepoint.com/sites/SiteName/'
fileName = 'c:/temp/upload.zip'
rootfolder = 'Documents'
targetfolder = '/PythonTests/'
ctx_auth = AuthenticationContext(url=fullurl)
if ctx_auth.acquire_token_for_app(client_id='redacted', client_secret='redacted'):
ctx = ClientContext(fullurl, ctx_auth)
target_list = ctx.web.lists.get_by_title(rootfolder)
info = FileCreationInformation()
with open(fileName, 'rb') as content_file:
info.content = content = content_file.read()
info.url = fileName
info.overwrite = True
upload_file = target_list.root_folder.files.add(fileName.split("/")[-1], info.content, overwrite=True)
ctx.execute_query()
except:
traceback.print_exc()
Exception has occurred: AttributeError
'NoneType' object has no attribute 'json'
File "C:\scripts\upload_to_sharepoint.py", line 20, in <module>
ctx.execute_query()
AttributeError: 'NoneType' object has no attribute 'json'
Traceback:
Traceback (most recent call last):
File "C:\Code\Python\Office365-REST\upload_to_sharepoint.py", line 22, in <module>
ctx.execute_query()
File "C:\Python\Python38\lib\site-packages\office365\runtime\client_runtime_context.py", line 181, in execute_query
self.pending_request().execute_query(qry)
File "C:\Python\Python38\lib\site-packages\office365\runtime\client_request.py", line 58, in execute_query
response = self.execute_request_direct(request)
File "C:\Python\Python38\lib\site-packages\office365\runtime\client_request.py", line 70, in execute_request_direct
self.beforeExecute.notify(request)
File "C:\Python\Python38\lib\site-packages\office365\runtime\types\event_handler.py", line 21, in notify
listener(*args, **kwargs)
File "C:\Python\Python38\lib\site-packages\office365\sharepoint\client_context.py", line 221, in _build_modification_query
self._ensure_form_digest(request)
File "C:\Python\Python38\lib\site-packages\office365\sharepoint\client_context.py", line 157, in _ensure_form_digest
self._ctx_web_info = self._get_context_web_information()
File "C:\Python\Python38\lib\site-packages\office365\sharepoint\client_context.py", line 170, in _get_context_web_information
client.map_json(response.json(), return_value, json_format)
AttributeError: 'NoneType' object has no attribute 'json'
I noticed that the request.auth was None
, and there are no headers listed in request.headers when the post is made to the /contextInfo
URL. However, I am authenticated according to the AuthenticationContext
return. I'm also successfully getting the target_list
. I'm unsure where to go from here. Thank you in advance for any help.
EDIT
Updated the code above based on the suggestion for {fullurl}
on line 14.
I decided to use the Graph API Explorer to test some methods and noticed a couple of items which may be influencing this issue. First, when I do a GET request to the site drives, there is nothing in the values list.
GET https://graph.microsoft.com/v1.0/sites/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/drives
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#drives",
"value": []
}
Without identifying a drive, the library name wouldn't resolve, correct?
If I try to retrieve the details of the default drive, I get access is denied.
GET https://graph.microsoft.com/v1.0/sites/root:/sites/SiteName:/drive
{
"error": {
"code": "accessDenied",
"message": "Access denied",
"innerError": {
"date": "2023-08-01T16:49:31",
"request-id": "9b9b9ff7-cd93-4a55-8f8c-14035c3f03e2",
"client-request-id": "f0761f22-91af-8740-cdfa-987715aeab89"
}
}
}
I am not the owner of the Sharepoint group, so I believe the issue stems from my permisisons. I am working to get elevated permissions to see if that addresses anything.
EDIT #2
Following the suggestion to use a more recent version of the API, I updated and tried the following, but still received the JSON error.
import os
from office365.sharepoint.client_context import ClientContext
from office365.runtime.auth.client_credential import ClientCredential
def print_upload_progress(offset):
file_size = os.path.getsize(local_path)
print("Uploaded '{0}' bytes from '{1}'...[{2}%]".format(offset, file_size, round(offset / file_size * 100, 2)))
ctx = ClientContext('https://org.sharepoint.com/sites/SiteName/').with_credentials(ClientCredential(client_id='redacted', client_secret='redacted'))
target_url = "Shared Documents/PythonTests"
target_folder = ctx.web.get_folder_by_server_relative_url(target_url)
size_chunk = 1000000
local_path = "c:/temp/upload.zip"
with open(local_path, 'rb') as f:
uploaded_file = target_folder.files.create_upload_session(f, size_chunk,
print_upload_progress).execute_query()
print('File {0} has been uploaded successfully'.format(uploaded_file.serverRelativeUrl))
Traceback (most recent call last):
File "C:\Code\Python\Office365-REST\upload_to_sharepoint_user_updated.py", line 24, in <module>
uploaded_file = target_folder.files.create_upload_session(f, size_chunk,
File "C:\Python\Python38\lib\site-packages\office365\runtime\client_object.py", line 44, in execute_query
self.context.execute_query()
File "C:\Python\Python38\lib\site-packages\office365\runtime\client_runtime_context.py", line 181, in execute_query
self.pending_request().execute_query(qry)
File "C:\Python\Python38\lib\site-packages\office365\runtime\client_request.py", line 57, in execute_query
response = self.execute_request_direct(request)
File "C:\Python\Python38\lib\site-packages\office365\runtime\client_request.py", line 69, in execute_request_direct
self.beforeExecute.notify(request)
File "C:\Python\Python38\lib\site-packages\office365\runtime\types\event_handler.py", line 21, in notify
listener(*args, **kwargs)
File "C:\Python\Python38\lib\site-packages\office365\sharepoint\client_context.py", line 222, in _build_modification_query
self._ensure_form_digest(request)
File "C:\Python\Python38\lib\site-packages\office365\sharepoint\client_context.py", line 157, in _ensure_form_digest
self._ctx_web_info = self._get_context_web_information()
File "C:\Python\Python38\lib\site-packages\office365\sharepoint\client_context.py", line 171, in _get_context_web_information
client.map_json(response.json(), return_value, json_format)
AttributeError: 'NoneType' object has no attribute 'json'
The same error is thrown. I did some more digging and I noticed this site is made from a Microsoft Team, and now I'm wondering if the structure of a Sharepoint Site made by Teams differs from a non-Team site?
EDIT #3
I have replicated the issue on a completely different Sharepoint site, and ruled out the possibility it was because Teams created a site. We tested on new sites created both ways in the second Sharepoint site, and still there are issues with the request being made from the module. At this point, I am looking to change to PowerShell and hope this get around the issues that are being presented by the Office365 module.
EDIT - Answer irrelevant, OP updated the code, still having issues.
On line 14, instantiating
ClientContext
, a literal{fullurl}
is provided as the first argument, while an actual URL is expected there (e.g.https://org.sharepoint.com/...
).To provide it with the actual URL as provided to
AuthenticationContext
, simply remove the single-quotation marks ('
) and the curly-brackets ({}
), like so:In case that f-string parsing is somehow required (although not demonstrated in the question) - an
f
should be prepended to the literal string, like so: