Office365-rest-python-client: Sharepoint์— ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒํ•ด์•ผํ•ฉ๋‹ˆ๊นŒ?

์— ๋งŒ๋“  2017๋…„ 07์›” 14์ผ  ยท  10์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: vgrem/Office365-REST-Python-Client

Sharepoint์— ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•˜๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค. ์˜ฌ๋ฐ”๋ฅธ ๊ฒฝ๋กœ์— ์žˆ์Šต๋‹ˆ๊นŒ?

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)
question

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

@benpolinsky ์Šค ๋‹ˆํŽซ์„ ๊ฒŒ์‹œ ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ฒ˜์Œ์—๋Š” ์–‘์‹ ๋‹ค์ด์ œ์ŠคํŠธ๋ฅผ ์–ป๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์ง€๋งŒ ๋ฐฉ๋ฒ•์„ ์•Œ์•„ ๋‚ด๋ฉด ํšจ๊ณผ๊ฐ€์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

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']

๋ชจ๋“  10 ๋Œ“๊ธ€

์ €๋Š” ์ด๊ฒƒ์„ํ•˜๊ธฐ ์œ„ํ•ด ClientRequest class ๋งŒ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

   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" 

@benpolinsky ์Šค ๋‹ˆํŽซ์„ ๊ฒŒ์‹œ ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ฒ˜์Œ์—๋Š” ์–‘์‹ ๋‹ค์ด์ œ์ŠคํŠธ๋ฅผ ์–ป๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์ง€๋งŒ ๋ฐฉ๋ฒ•์„ ์•Œ์•„ ๋‚ด๋ฉด ํšจ๊ณผ๊ฐ€์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

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']

SharePoint์— ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•˜๋Š” ๊ฐ„๋‹จํ•œ API๋ฅผ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋„ˆ๋ฌด ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค.

@attibalazs ์Šคํฌ๋ฆฝํŠธ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ํ˜„์žฌ ์—ฌ๊ธฐ์— ๊ฐ‡ํ˜€ ์žˆ์Šต๋‹ˆ๋‹ค.

get_authentication_cookie์—์žˆ๋Š” ํŒŒ์ผ "C : \ Python27 \ lib \ site-packages \ office365 \ runtime \ auth \ saml_token_provider.py", 65 ํ–‰
return 'FedAuth ='+ self.FedAuth + '; rtFa = '+ self.rtFa
TypeError : 'str'๋ฐ 'NoneType'๊ฐœ์ฒด๋ฅผ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

SP Online URL, ์‚ฌ์šฉ์ž ์ด๋ฆ„ ๋ฐ ์•”ํ˜ธ ์™ธ์— ํด๋ผ์ด์–ธํŠธ ID์™€ ํด๋ผ์ด์–ธํŠธ ์•”ํ˜ธ๋„ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๊นŒ?

์ด @attibalazs ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ž˜ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ์ฝ”๋“œ๋Š” [email protected] ๊ณผ ๊ฐ™์€ ์กฐ์ง ๊ณ„์ •์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๊นŒ ์•„๋‹ˆ๋ฉด [email protected] ๊ณผ ๊ฐ™์€ ์ ์ ˆํ•œ office365 ๊ณ„์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๊นŒ?

์•ˆ๋…•ํ•˜์„ธ์š”, @attibalazs ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉ
data = requests.post(url=full_url, data=outfile, headers=options.headers, auth=options.auth)

403 ์ƒํƒœ๋ฅผ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ Sharepoint์—์„œ ์“ฐ๊ธฐ ๊ถŒํ•œ์„ ์–ป์œผ๋ ค๋ฉด ๋‚ด ์‚ฌ๋ฌด์‹ค ๊ณ„์ • ๊ตฌ์„ฑ์—์„œ ๋ณ€๊ฒฝํ•ด์•ผ ํ•  ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๋ฟก ๋นต๋€จ
API๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. status = status = ctx_auth.acquire_token_for_user (username, password) ๋Œ€์‹  ctx_auth.acquire_token_for_app ()
ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜์‹ญ์‹œ์˜ค. pip ์„ค์น˜ -U ์ธ์ฆ์„œ

์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋ฅผ ์œ„ํ•ด ์ž‘๋™ํ•˜๋Š” ์ฝ”๋“œ์— ๋ช‡ ๊ฐ€์ง€ ์กฐ์ •์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

Sharepoint์— ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•˜๋ ค๊ณ ํ•ฉ๋‹ˆ๋‹ค. ์˜ฌ๋ฐ”๋ฅธ ๊ฒฝ๋กœ์— ์žˆ์Šต๋‹ˆ๊นŒ?

```
def upload_file (ctx, listTitle, ๊ฒฝ๋กœ) :
list_obj = ctx.web.lists.get_by_title (listTitle)
ํด๋” = list_obj.root_folder
ctx.load (ํด๋”)
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()

์ธ์‚ฌ๋ง,

๋‚˜๋Š” ๋‹ต๋ณ€์„ ๋ฐ›์•˜์œผ๋ฏ€๋กœ ์ด๊ฒƒ์„ ๋‹ซ์„ ๊ฒƒ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

์š”์•ฝ:

SharePoint ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•˜๋Š” ๊ถŒ์žฅ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

#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()

๊ทธ๋Ÿฌ๋‚˜ ํŒŒ์ผ์ด 2MB๋ณด๋‹ค ํฌ๋ฉด ํŒŒ์ผ์„ ์ฒญํฌ ์ง‘ํ•ฉ์œผ๋กœ ์—…๋กœ๋“œํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

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']))

์–ด๋””

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

์ง์ ‘ ์—…๋กœ๋“œ ์š”์ฒญ์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•˜๋Š” ๊ฒฝ์šฐ @attibalazs ๋ฐ @benpolinsky์—์„œ ์ œ๊ณตํ•˜๋Š” ์Šค ๋‹ˆํŽซ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค .

๋ฐ”๋”ค

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰