2016-10-11 51 views
6

Có thể tải lên một tập tin vào Shared Documents thư viện của Microsoft SharePoint trang web với Python OneDrive SDK?Upload để MS SharePoint sử dụng Python onedrive SDK

This documentation nói rằng phải là (trong câu đầu tiên), nhưng tôi không thể làm cho nó hoạt động.

tôi có thể xác thực (với Azure AD) và tải lên một thư mục onedrive, nhưng khi cố gắng để tải lên một SharePoint thư mục, tôi tiếp tục nhận được lỗi này:

"Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown."

Các mã tôi đang sử dụng mà trả về một đối tượng với các lỗi:

(...authentication...) 
client = onedrivesdk.OneDriveClient('https://{tenant}.sharepoint.com/{site}/_api/v2.0/', auth, http) 
client.item(path='/drive/special/documents').children['test.xlsx'].upload('test.xlsx') 

where I'd like to upload on the web

.210

tôi thành công có thể tải lên https://{tenant}-my.sharepoint.com/_api/v2.0/ (chú ý "-my" sau khi {tenant}) với đoạn mã sau:

client = onedrivesdk.OneDriveClient('https://{tenant}-my.sharepoint.com/_api/v2.0/', auth, http) 
returned_item = client.item(drive='me', id='root').children['test.xlsx'].upload('test.xlsx') 

Làm thế nào tôi có thể tải lên các tập tin cùng một SharePoint trang web?

(Câu trả lời cho câu hỏi tương tự (1, 2, 3, 4) trên Stack Overflow hoặc là quá mơ hồ hoặc đề nghị sử dụng một API khác nhau. Câu hỏi của tôi là nếu nó có thể sử dụng onedrive Python SDK, và nếu như vậy, làm thế nào để làm điều đó)


cập nhật:. đây là mã đầy đủ của tôi và đầu ra. (dữ liệu gốc Sensitive thay thế bằng định dạng tương tự vô nghia.)

import re 
import onedrivesdk 
from onedrivesdk.helpers.resource_discovery import ResourceDiscoveryRequest 

# our domain (not the original) 
redirect_uri = 'https://example.ourdomain.net/' 
# our client id (not the original) 
client_id = "a1234567-1ab2-1234-a123-ab1234abc123" 
# our client secret (not the original) 
client_secret = 'ABCaDEFGbHcd0e1I2fghJijkL3mn4M5NO67P8Qopq+r=' 
resource = 'https://api.office.com/discovery/' 
auth_server_url = 'https://login.microsoftonline.com/common/oauth2/authorize' 
auth_token_url = 'https://login.microsoftonline.com/common/oauth2/token' 
http = onedrivesdk.HttpProvider() 
auth = onedrivesdk.AuthProvider(http_provider=http, client_id=client_id, 
           auth_server_url=auth_server_url, 
           auth_token_url=auth_token_url) 

should_authenticate_via_browser = False 
try: 
    # Look for a saved session. If not found, we'll have to 
    # authenticate by opening the browser. 
    auth.load_session() 
    auth.refresh_token() 
except FileNotFoundError as e: 
    should_authenticate_via_browser = True 
    pass 

if should_authenticate_via_browser: 
    auth_url = auth.get_auth_url(redirect_uri) 
    code = '' 
    while not re.match(r'[a-zA-Z0-9_-]+', code): 
     # Ask for the code 
     print('Paste this URL into your browser, approve the app\'s access.') 
     print('Copy the resulting URL and paste it below.') 
     print(auth_url) 
     code = input('Paste code here: ') 
     # Parse code from URL if necessary 
     if re.match(r'.*?code=([a-zA-Z0-9_-]+).*', code): 
      code = re.sub(r'.*?code=([a-zA-Z0-9_-]*).*', r'\1', code) 
    auth.authenticate(code, redirect_uri, client_secret, resource=resource) 
    # If you have access to more than one service, you'll need to decide 
    # which ServiceInfo to use instead of just using the first one, as below. 
    service_info = ResourceDiscoveryRequest().get_service_info(auth.access_token)[0] 
    auth.redeem_refresh_token(service_info.service_resource_id) 
    auth.save_session() # Save session into a local file. 

# Doesn't work 
client = onedrivesdk.OneDriveClient(
    'https://{tenant}.sharepoint.com/sites/{site}/_api/v2.0/', auth, http) 
returned_item = client.item(path='/drive/special/documents') 
         .children['test.xlsx'] 
         .upload('test.xlsx') 
print(returned_item._prop_dict['error_description']) 

# Works, uploads to OneDrive instead of SharePoint site 
client2 = onedrivesdk.OneDriveClient(
    'https://{tenant}-my.sharepoint.com/_api/v2.0/', auth, http) 
returned_item2 = client2.item(drive='me', id='root') 
         .children['test.xlsx'] 
         .upload('test.xlsx') 
print(returned_item2.web_url) 

Output:

Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown. 
https://{tenant}-my.sharepoint.com/personal/user_domain_net/_layouts/15/WopiFrame.aspx?sourcedoc=%1ABCDE2345-67F8-9012-3G45-6H78IJKL9M01%2N&file=test.xlsx&action=default 
+0

Bạn có thể cung cấp truy xuất đầy đủ không? Hoặc chỉ định dòng nào là nguồn của lỗi dòng bắt đầu bằng 'client' hoặc' return_item'? – sytech

+0

Ngoài ra, bạn có [đặt AuthScope thích hợp] (https://github.com/OneDrive/onedrive-api-docs/blob/master/site-images/AuthScopesForSharePoint.png?raw=true) cho SharePoint Online không? Điều này tách biệt với quyền OneDrive của bạn. – sytech

+0

@Gator_Python - Tôi đã thêm mã đầy đủ. Không có lỗi nào bị ném, nhưng đối tượng trả về chứa các thuộc tính của tệp được tải lên trong trường hợp thành công và thông báo lỗi này trong trường hợp không thành công. AuthScope được thiết lập như vậy (trên thực tế, tất cả các quyền đều được đánh dấu). –

Trả lời

3

tôi cuối cùng đã tìm thấy một giải pháp, với sự giúp đỡ của (SO sử dụng) sytech.

Câu trả lời cho câu hỏi ban đầu của tôi là sử dụng bản gốc Python OneDrive SDK, nó không thể để tải lên một tập tin vào thư mục Shared Documents của một trang web SharePoint Online (tại thời điểm viết bài này): khi SDK truy vấn resource discovery service, nó giảm tất cả các dịch vụ có service_api_version không phải là v2.0. Tuy nhiên, tôi nhận được dịch vụ SharePoint với v1.0, do đó, dịch vụ này bị loại bỏ, mặc dù nó có thể được truy cập bằng API v2.0.

Tuy nhiên, bằng cách mở rộng lớp ResourceDiscoveryRequest (trong OneDrive SDK), chúng tôi có thể tạo giải pháp cho việc này.Tôi quản lý để tải lên một tập tin theo cách này:

import json 
import re 
import onedrivesdk 
import requests 
from onedrivesdk.helpers.resource_discovery import ResourceDiscoveryRequest, \ 
    ServiceInfo 

# our domain (not the original) 
redirect_uri = 'https://example.ourdomain.net/' 
# our client id (not the original) 
client_id = "a1234567-1ab2-1234-a123-ab1234abc123" 
# our client secret (not the original) 
client_secret = 'ABCaDEFGbHcd0e1I2fghJijkL3mn4M5NO67P8Qopq+r=' 
resource = 'https://api.office.com/discovery/' 
auth_server_url = 'https://login.microsoftonline.com/common/oauth2/authorize' 
auth_token_url = 'https://login.microsoftonline.com/common/oauth2/token' 

# our sharepoint URL (not the original) 
sharepoint_base_url = 'https://{tenant}.sharepoint.com/' 
# our site URL (not the original) 
sharepoint_site_url = sharepoint_base_url + 'sites/{site}' 

file_to_upload = 'C:/test.xlsx' 
target_filename = 'test.xlsx' 


class AnyVersionResourceDiscoveryRequest(ResourceDiscoveryRequest): 

    def get_all_service_info(self, access_token, sharepoint_base_url): 
     headers = {'Authorization': 'Bearer ' + access_token} 
     response = json.loads(requests.get(self._discovery_service_url, 
              headers=headers).text) 
     service_info_list = [ServiceInfo(x) for x in response['value']] 
     # Get all services, not just the ones with service_api_version 'v2.0' 
     # Filter only on service_resource_id 
     sharepoint_services = \ 
      [si for si in service_info_list 
      if si.service_resource_id == sharepoint_base_url] 
     return sharepoint_services 


http = onedrivesdk.HttpProvider() 
auth = onedrivesdk.AuthProvider(http_provider=http, client_id=client_id, 
           auth_server_url=auth_server_url, 
           auth_token_url=auth_token_url) 

should_authenticate_via_browser = False 
try: 
    # Look for a saved session. If not found, we'll have to 
    # authenticate by opening the browser. 
    auth.load_session() 
    auth.refresh_token() 
except FileNotFoundError as e: 
    should_authenticate_via_browser = True 
    pass 

if should_authenticate_via_browser: 
    auth_url = auth.get_auth_url(redirect_uri) 
    code = '' 
    while not re.match(r'[a-zA-Z0-9_-]+', code): 
     # Ask for the code 
     print('Paste this URL into your browser, approve the app\'s access.') 
     print('Copy the resulting URL and paste it below.') 
     print(auth_url) 
     code = input('Paste code here: ') 
     # Parse code from URL if necessary 
     if re.match(r'.*?code=([a-zA-Z0-9_-]+).*', code): 
      code = re.sub(r'.*?code=([a-zA-Z0-9_-]*).*', r'\1', code) 

    auth.authenticate(code, redirect_uri, client_secret, resource=resource) 
    service_info = AnyVersionResourceDiscoveryRequest().\ 
     get_all_service_info(auth.access_token, sharepoint_base_url)[0] 
    auth.redeem_refresh_token(service_info.service_resource_id) 
    auth.save_session() 

client = onedrivesdk.OneDriveClient(sharepoint_site_url + '/_api/v2.0/', 
            auth, http) 
# Get the drive ID of the Documents folder. 
documents_drive_id = [x['id'] 
         for x 
         in client.drives.get()._prop_list 
         if x['name'] == 'Documents'][0] 
items = client.item(drive=documents_drive_id, id='root') 
# Upload file 
uploaded_file_info = items.children[target_filename].upload(file_to_upload) 

xác thực cho một dịch vụ khác nhau mang đến cho bạn một mã thông báo khác nhau.

+0

Mã có vẻ tốt, nhưng mã tôi đang viết cần được tự động, vì vậy tôi không thể sao chép và dán "mã" được tạo bởi trình duyệt mỗi lần, "mã" này cũng sẽ hết hạn sớm. Vì vậy, dựa trên mã của bạn, tôi đã sửa đổi mã của mình, nhưng không có vấn đề gì là v1.0 hoặc v2.0, tôi vẫn nhận được phản hồi trống ['value'] ..... Tôi có thể hỏi, bạn có biết điều gì sai với mã? Đây là mã của tôi: https://github.com/hanhanwu/Basic_But_Useful/blob/master/one_drive_buz_test.py –

+0

@CherryWu - Mã ở trên _is_ được tự động hóa. 'auth.save_session()' lưu thông tin xác thực vào một tập tin gọi là 'session.pickle'. 'auth.load_session()' tải này. Cách nó hoạt động là lần đầu tiên bạn chạy mã này, nó sẽ mở ra một cửa sổ trình duyệt mà bạn cần đăng nhập và sao chép và dán URL sau khi chuyển hướng trở lại bảng điều khiển Python. Mã thông báo xác thực này sau đó được lưu và lần tiếp theo được tải mà không cần mở trình duyệt. Bạn có thể đọc thêm về điều này tại phần "Lưu và tải phiên" [ở đây] (https://github.com/OneDrive/onedrive-sdk-python). –

+0

Cảm ơn bạn rất nhiều Attila, hôm nay tôi không có thời gian để thử điều này, nhưng một câu hỏi nhanh, mã chúng tôi nhận được từ trình duyệt có tuổi thọ rất ngắn, điều này có nghĩa là, với "Tiết kiệm và tải một phiên" trong mã của bạn, "mã" đó sẽ không còn hết hạn? –

Các vấn đề liên quan