OneDrive 无管理员调用API

  • by

受到Onesrc(链接:https://www.onesrc.cn/p/how-to-call-api-for-onedrive-account-without-administrator.html)大佬的启发,出于发挥无管理员OneDrive的优势,写了个小程序,这种API调用方法有限制,可以列文件,上传下载,但是不能删除,而且基于静态链接也有一定的安全风险,有效期未知(估计也有几个小时吧!)

实际上就是FedAuth换取Token,如果用更高权限,也可以用selenium模拟登录后获取(也就多了删除,创建目录权限,依然不能跨目录操作).

操作方法,首先新建一个文件夹:

给文件夹Share权限,所有人可编辑.

替换示例程序中的url和shared_folder,大文件上传我使用了一个音乐文件,也需要替换.

import json
import os

import requests

# 权限列表(限定于分享的文件夹内)
#
# 列文件 Yes
# 上传文件 Yes
# 下载文件 Yes
# 删除文件 No
# 创建文件夹 No

url = "https://alumnibentley-my.sharepoint.com/:f:/g/personal/rita_odin_alumni_bentley_edu/EmGOHZZfTiRAqe6VmccZ5C8BDvQelTCL1jqDRkg6w1T4oQ?e=8iQeCu"

shared_folder = 'Files'
tenant = url.split('/')[2]
mail = url.split('/')[6]

response = requests.get(url)
cookies = response.cookies.get_dict()
print('提取 FedAuth:' + cookies['FedAuth'])

url = "https://" + tenant + "/personal/" + mail + "/_api/web/GetListUsingPath(DecodedUrl=@a1)/RenderListDataAsStream?@a1='/personal/" + mail + "/Documents'&RootFolder=/personal/" + mail + "/Documents/&TryNewExperienceSingle=TRUE"

headers = {
    'Accept': 'application/json;odata=verbose',
    'Content-Type': 'application/json;odata=verbose'
}

payload = {
    "parameters": {
        "__metadata": {"type": "SP.RenderListDataParameters"},
        "RenderOptions": 136967,
        "AllowMultipleValueFilterForTaxonomyFields": True,
        "AddRequiredFields": True
    }
}

response = requests.post(url, cookies=cookies, headers=headers, data=json.dumps(payload))

payload = json.loads(response.text)
token = payload['ListSchema']['.driveAccessToken'][13:]
api_url = payload['ListSchema']['.driveUrl'] + '/'
print('提取 AccessToken:' + token)
print('提取 api_url:' + api_url)

headers = {
    'Authorization': 'Bearer ' + token
}
response = requests.get(api_url + 'root/', headers=headers)
folder_id = json.loads(response.text)['id']
print('提取 根目录ID:' + folder_id)

headers = {
    'Authorization': 'Bearer ' + token
}
response = requests.get(api_url + 'root:/' + shared_folder + ':/children', headers=headers)
files = json.loads(response.text)['value']
print('列举目录内文件:')
for mfile in files:
    print(' 文件 =>' + mfile['name'])

# 普通上传最大4MB
headers = {
    'Authorization': 'Bearer ' + token,
    'Content-Type': 'application/json'
}
response = requests.put(api_url + 'items/root:/' + shared_folder + '/460.txt:/content', headers=headers, data='Test')
file_id = json.loads(response.text)['id']
print('提取 文件ID:' + file_id)

headers = {
    'Authorization': 'Bearer ' + token,
    'Content-Type': 'application/json'
}
response = requests.get(api_url + 'items/' + file_id + '/content', headers=headers, allow_redirects=False)
download_link = response.headers['Location']
print('提取 文件下载直链:' + download_link)

# 多部份上传最大15G
headers = {
    'Authorization': 'Bearer ' + token,
    'Content-Type': 'application/json'
}

response = requests.post(api_url + 'items/root:/' + shared_folder + '/画纸上的戒指.mp3:/createUploadSession', headers=headers)
uploadUrl = json.loads(response.text)['uploadUrl']

file_size = os.path.getsize('画纸上的戒指.mp3')
with open('画纸上的戒指.mp3', "rb") as file:
    while True:
        data = file.read(1024 * 1024)
        if not data:
            file_id = json.loads(response.text)['id']
            print('提取 文件ID:' + file_id)
            break

        headers = {
            'Content-Length': str(len(data)),
            'Content-Range': 'bytes ' + str(file.tell() - len(data)) + '-' + str(file.tell() - 1) + '/' + str(file_size)
        }

        print('正在上传:' + str(round((file.tell() * 100) / file_size, 2)) + '%')
        response = requests.put(uploadUrl, headers=headers, data=data)

测试结果:

再说一次,只有主用户可以删除文件,在这个特殊API上传的文件在主用户下也可以随便挪动.

快速测试代码:

https://gist.github.com/nickfox-taterli/d0f5932e05ff2f2490f38c42f191406e

传入第一个参数是分享URL,第二个参数是对应的文件.

上传结果:

发表评论

电子邮件地址不会被公开。 必填项已用*标注