Office365-REST-Python-Client icon indicating copy to clipboard operation
Office365-REST-Python-Client copied to clipboard

URL limit hit when preforming moveto and copyto

Open thomasfrederikhoeck opened this issue 5 years ago • 13 comments

SharePoint API has a limit to the length of the URL which can be used for the API at 260 characters. This is not normally a problem but if you are performing MoveTo or CopyTo, where the files are located deep in the folders the limits can easily be hit.

Right now the relative URL is used to signal which file to move but if the library switched to using the unique file id then this probelm would be much smaller (see https://stackoverflow.com/questions/36172818/url-length-limitation-in-sharepoint-online-rest).

thomasfrederikhoeck avatar Feb 03 '21 08:02 thomasfrederikhoeck

@trinebrockhoff

thomasfrederikhoeck avatar Feb 03 '21 08:02 thomasfrederikhoeck

Hello, I'm also running into this problem, will there be a fix or is a workaround available ?

Albarion avatar Aug 02 '21 13:08 Albarion

I created a workaround using some of Microsoft's documentation on moveto. I think copyto could be swapped in easily but I did not verify. It uses RequestOptions to make the REST query manually. I tried to use 'public' methods from the library whenever possible.

# additional imports
from office365.runtime.http.request_options import RequestOptions
from office365.runtime.odata.path_builder import ODataPathBuilder

# ...

file = CTX.web.get_file_by_server_relative_url(source_filepath).get().execute_query()
file_id = file.unique_id

get_file_query_string = "getFileById('{}')".format(file_id)

moveto_query_params = {'newurl': future_filepath, 'flags': 1}
moveto_query_string = ODataPathBuilder.build('moveto', moveto_query_params)

moveto_url = '/'.join([CTX.service_root_url(), 'web', get_file_query_string, moveto_query_string])
request = RequestOptions(moveto_url)
request.method = 'POST'
CTX.pending_request().execute_request_direct(request)

EDIT: I updated the workaround per changes in the commit: https://github.com/vgrem/Office365-REST-Python-Client/commit/693520b24853b8e4321eaf28ba21034601dc7659

dvinesett avatar Apr 29 '22 05:04 dvinesett

I updated my workaround to no longer use moveto() from office365.sharepoint.files.file. Instead, I just hardcode the method_name when building the ODataPath. Calling moveto was unnecessary and had the side affect of adding a moveto query into the context's _queries list.

dvinesett avatar Apr 30 '22 23:04 dvinesett

I'm also running into this problem. Unfortunately the workaround returns an error 403 for me, with the following message: '{"error":{"code":"-2130575251, Microsoft.SharePoint.SPException","message":{"lang":"en-US","value":"The security validation for this page is invalid and might be corrupted. Please use your web browser\'s Back button to try your operation again."}}}'

I have authenticated using the following method and this has worked for me with built-in queries until now: CTX= (ClientContext(site_url).with_credentials(UserCredential(username, password)))

Do you have any suggestions on how to fix this?

mwmg avatar Aug 16 '22 09:08 mwmg

I'm also running into this problem. Unfortunately the workaround returns an error 403 for me, with the following message: '{"error":{"code":"-2130575251, Microsoft.SharePoint.SPException","message":{"lang":"en-US","value":"The security validation for this page is invalid and might be corrupted. Please use your web browser\'s Back button to try your operation again."}}}'

I have authenticated using the following method and this has worked for me with built-in queries until now: CTX= (ClientContext(site_url).with_credentials(UserCredential(username, password)))

Do you have any suggestions on how to fix this?

I've faced the same issue. The fix is: CTX.ensure_form_digest(request) this will add X-RequestDigest to the header.

oliaboo avatar Sep 05 '22 16:09 oliaboo

Thank you, that worked!

mwmg avatar Sep 08 '22 12:09 mwmg

It looks like a recent commit broke my workaround. The updated README was helpful in correcting its methodology. I've fixed it on the original comment: https://github.com/vgrem/Office365-REST-Python-Client/issues/319#issuecomment-1112892198

Note-- the change was committed after the problem reported above: https://github.com/vgrem/Office365-REST-Python-Client/issues/319#issuecomment-1216386742

dvinesett avatar Sep 14 '22 23:09 dvinesett

I created a workaround using some of Microsoft's documentation on moveto. I think copyto could be swapped in easily but I did not verify. It uses RequestOptions to make the REST query manually. I tried to use 'public' methods from the library whenever possible.

# additional imports
from office365.runtime.http.request_options import RequestOptions
from office365.runtime.odata.path_builder import ODataPathBuilder

# ...

file = CTX.web.get_file_by_server_relative_url(source_filepath).get().execute_query()
file_id = file.unique_id

get_file_query_string = "getFileById('{}')".format(file_id)

moveto_query_params = {'newurl': future_filepath, 'flags': 1}
moveto_query_string = ODataPathBuilder.build('moveto', moveto_query_params)

moveto_url = '/'.join([CTX.service_root_url(), 'web', get_file_query_string, moveto_query_string])
request = RequestOptions(moveto_url)
request.method = 'POST'
CTX.pending_request().execute_request_direct(request)

EDIT: I updated the workaround per changes in the commit: 693520b

Can you please share code to copy instead of move

skyashin avatar Mar 08 '23 13:03 skyashin

Can you please share the code to COPY instead of MOVE using ODATA method?

skyashin avatar Mar 08 '23 13:03 skyashin

I created a workaround using some of Microsoft's documentation on moveto. I think copyto could be swapped in easily but I did not verify. It uses RequestOptions to make the REST query manually. I tried to use 'public' methods from the library whenever possible.

# additional imports
from office365.runtime.http.request_options import RequestOptions
from office365.runtime.odata.path_builder import ODataPathBuilder

# ...

file = CTX.web.get_file_by_server_relative_url(source_filepath).get().execute_query()
file_id = file.unique_id

get_file_query_string = "getFileById('{}')".format(file_id)

moveto_query_params = {'newurl': future_filepath, 'flags': 1}
moveto_query_string = ODataPathBuilder.build('moveto', moveto_query_params)

moveto_url = '/'.join([CTX.service_root_url(), 'web', get_file_query_string, moveto_query_string])
request = RequestOptions(moveto_url)
request.method = 'POST'
CTX.pending_request().execute_request_direct(request)

EDIT: I updated the workaround per changes in the commit: 693520b

Hello, thanks for the workaround! I just needed to update following the renaming of ODataPathBuilder (commit: 74f95a9):


# additional imports
from office365.runtime.http.request_options import RequestOptions
from office365.runtime.odata.url_builder import ODataUrlBuilder
# from office365.runtime.odata.path_builder import ODataPathBuilder # old

# ...

file = CTX.web.get_file_by_server_relative_url(source_filepath).get().execute_query()
file_id = file.unique_id

get_file_query_string = "getFileById('{}')".format(file_id)

moveto_query_params = {'newurl': future_filepath, 'flags': 1}
moveto_query_string = ODataUrlBuilder.build('moveto', moveto_query_params)

moveto_url = '/'.join([CTX.service_root_url(), 'web', get_file_query_string, moveto_query_string])
request = RequestOptions(moveto_url)
request.method = 'POST'
CTX.pending_request().execute_request_direct(request)

FedericoRaimondi avatar Apr 26 '23 09:04 FedericoRaimondi