使用Python上传文件至OneDrive失败,报400错误求助
解决OneDrive上传时的BadRequest错误
错误原因分析
你遇到的/me request is only valid with delegated authentication flow错误,核心问题是认证方式不匹配:
- 你用的是
acquire_token_with_client_credentials(客户端凭据流),这是服务到服务的认证模式,没有关联具体用户账户,因此API路径里的/me(代表当前登录用户)无法被识别。 - 只有委托权限流(比如授权码流)会绑定用户上下文,才能使用
/me路径。
解决方案1:上传到指定用户的OneDrive(OneDrive for Business场景)
如果目标是上传到租户内特定用户的OneDrive,直接指定用户ID或邮箱(UPN)即可,无需使用/me:
修改API请求路径:
# 替换{user-id}为目标用户的ID,或用户邮箱(如user@contoso.com) url = "https://graph.microsoft.com/v1.0/users/{user-id}/drive/root/children/Texto.txt/content"
完整修改后的代码示例:
import adal import json import requests AUTHORITY_URL = 'https://login.microsoftonline.com/{}'.format('TENANT-ID') CLIENT_ID = 'Client ID' CLIENT_SECRET = 'Client Secret' RESOURCE = 'https://graph.microsoft.com/' # 获取token(这部分保留) context = adal.AuthenticationContext(AUTHORITY_URL) token = context.acquire_token_with_client_credentials(RESOURCE, CLIENT_ID, CLIENT_SECRET) # 修改URL,指定具体用户 user_id = "目标用户的ID或邮箱" url = f"https://graph.microsoft.com/v1.0/users/{user_id}/drive/root/children/Texto.txt/content" file_path = "Texto.txt" headers = {"Authorization": "Bearer " + token["accessToken"]} with open(file_path, "rb") as f: content = f.read() response = requests.put(url, data=content, headers=headers) print(response.text)
注意:这种方式需要你的应用注册时添加应用权限(而非委托权限),比如Files.ReadWrite.All,并且需要租户管理员同意该权限。
解决方案2:使用委托权限流(个人OneDrive或需模拟用户操作场景)
如果是上传到个人OneDrive,或必须以用户身份操作,客户端凭据流不适用,需改用授权码流(委托权限)。另外ADAL已被微软弃用,建议改用MSAL库:
- 先安装MSAL:
pip install msal
- 示例代码(设备码流,适合无UI环境):
import msal import requests CLIENT_ID = "你的客户端ID" CLIENT_SECRET = "你的客户端密钥" TENANT_ID = "common" # 个人OneDrive用common,租户场景填租户ID AUTHORITY = f"https://login.microsoftonline.com/{TENANT_ID}" SCOPE = ["https://graph.microsoft.com/Files.ReadWrite"] # 初始化MSAL客户端 app = msal.ConfidentialClientApplication( CLIENT_ID, authority=AUTHORITY, client_credential=CLIENT_SECRET ) # 设备码流获取token result = app.acquire_token_by_device_flow(scopes=SCOPE) if "access_token" in result: access_token = result["access_token"] # 此时可使用/me路径 url = "https://graph.microsoft.com/v1.0/me/drive/root/children/Texto.txt/content" file_path = "Texto.txt" headers = {"Authorization": f"Bearer {access_token}"} with open(file_path, "rb") as f: content = f.read() response = requests.put(url, data=content, headers=headers) print(response.text) else: print(result.get("error"), result.get("error_description"))
说明:
- 设备码流运行时会输出链接和验证码,用户通过浏览器打开链接输入验证码即可完成授权,适合无界面服务器环境。
- 应用注册时需添加委托权限(如
Files.ReadWrite),个人OneDrive场景无需管理员同意,用户自行授权即可。
权限配置提醒
无论采用哪种方案,都要确保Azure AD应用注册中添加了对应权限:
- 客户端凭据流:添加应用权限,并请求租户管理员同意
- 委托权限流:添加委托权限,由用户自行同意
内容的提问来源于stack exchange,提问作者Adrian Noli
相关产品推荐
相关产品推荐

