JonathanHolvey / sharepy

Simple SharePoint authentication for Python
GNU General Public License v3.0
175 stars 52 forks source link

feature: upload file to sharepoint #4

Closed ledikari closed 6 years ago

ledikari commented 6 years ago

this is needed.

JonathanHolvey commented 6 years ago

SharePy isn't intended to be a wrapper for the SharePoint REST API, but an authentication mechanism for accessing it. I would consider adding more features for manipulating files etc, but it would require significant user demand.

You can upload a file to a SharePoint library using a POST request to the _api/web/GetFolderByServerRelativeUrl endpoint, as described by the REST API documentation.

The following snippet will allow you to upload a file and check it in:

url = "https://example.sharepoint.com/subsite/_api/web"

def upload(session, source, dest):
    s = session
    exists = False
    folder, file = os.path.split(dest)
    # Verify folder exists on server
    r = s.get(url + "GetFolderByServerRelativeUrl('{}')".format(folder))
    if r.status_code in [401, 403]:
        return False, "Access denied"
    elif r.status_code != 200:
        return False, "Folder '{}' does not exist on server".format(folder)
    else:
        # Check if file already exists
        r = s.get(url + "GetFileByServerRelativeUrl('{}')".format(dest))
        if r.status_code == 200:
            exists = True
            # Check file is checked out to current user
            r = s.get(url + "GetFileByServerRelativeUrl('{}')/CheckedOutByUser".format(dest))
            if "LoginName" in r.json()["d"]:
                user = re.sub(r"^.*\|", "", r.json()["d"]["LoginName"])
                if user != s.username:
                    return False, "File checked out to " + user
            else:
                r = s.post(url + "GetFileByServerRelativeUrl('{}')/Checkout()".format(dest))
                if r.status_code != 200:
                    return False, "File could not be checked out"

        # Upload file to server
        with open(source, "rb") as f:
            data = f.read()
        headers = {"content-length": len(data)}
        if exists:
            headers["X-HTTP-Method"] = "PUT"
            r = s.post(url + "GetFileByServerRelativeUrl('{}')/$value"
                       .format(dest), data=data, headers=headers)
        else:
            r = s.post(url + "GetFolderByServerRelativeUrl('{}')/Files/add(url='{}',overwrite=true)"
                       .format(folder, file), data=data, headers=headers)
        if r.status_code in (200, 204):
            return True, "File uploaded successfully"
        else:
            if "error" in r.json():
                error = "\n" + r.json()["error"]["message"]["value"]
            else:
                error = ""
            return False, ("Upload failed. Status {}{}".format(str(r.status_code), error))

def checkin(session, dest, comment=""):
    s = session
    r = s.post(url + "GetFileByServerRelativeUrl('{}')/CheckIn(comment='{}',checkintype=0)"
               .format(dest, urllib.parse.quote(comment.replace("'", "''").split("\n")[0])))
    if r.status_code == 200:
        return True, "File checked in successfully"
    else:
        return False, "File could not be checked in"

session = sharepy.connect("https://sharepoint.example.com")
source = "./file-to-upload.txt"
dest = "/path/to/library/file-to-upload.txt"

upload(session, source, dest)
checkin(session, dest, comment="Newly uploaded file")
ledikari commented 6 years ago

thank you very much. :)

you can close the issue right now, but i believe there are lots of people looking for this feature. I hope everybody can see this.