受到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,第二个参数是对应的文件.
上传结果: