You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python MSAL库下载OneDrive个人图片时遭遇401 'unauthenticated'错误

使用Python MSAL库下载OneDrive个人图片时遭遇401 'unauthenticated'错误

根据你的描述,你已经成功获取了有效的access token,并且能正常调用Graph API列出OneDrive中的文件,说明你的权限配置和token获取流程都是没问题的。出现401错误的核心原因,是你直接使用@microsoft.graph.downloadUrl这个链接时,缺少了该链接依赖的会话凭证——这个URL是一个预授权的临时链接,它和你浏览器登录时的会话绑定,而你的Python脚本直接请求它时,没有携带对应的会话Cookie,所以会被判定为未认证。

解决方案:使用Graph API标准端点下载文件

更可靠且符合规范的方式是直接通过Graph API的文件内容端点来下载,利用你已经持有的access token进行授权。具体步骤如下:

  1. 从文件列表的返回结果中,获取每个文件的id字段(而不是@microsoft.graph.downloadUrl)
  2. 构造Graph API的下载端点:https://graph.microsoft.com/v1.0/me/drive/items/{file-id}/content
  3. 使用你请求文件列表时的同一个headers(包含Authorization: Bearer {access_token})发送GET请求到该端点,即可获取文件二进制内容。

修改后的代码示例

在你现有的脚本基础上,添加下载文件的逻辑:

#!/usr/bin/python3

import requests
import json
from msal import PublicClientApplication

### config
app_id = '6cae2a2a-XXX'
authority = 'https://login.microsoftonline.com/consumers'
scopes = ["User.Read", "User.Export.All", "Files.ReadWrite.All"]

### start main ###

### create app 
app = PublicClientApplication(app_id, authority=authority)

### get access token
result = app.acquire_token_interactive(scopes)

if "access_token" in result:
    print("Got access_token: " + result["access_token"])
else:
    print(result.get("error"))
    print(result.get("error_description"))
    print(result.get("correlation_id"))  # You may need this when reporting a bug
    exit()

### 设置请求头
headers = {
    "Authorization": "Bearer " + result["access_token"]
}

### 1. 获取文件列表
request_url = 'https://graph.microsoft.com/v1.0/me/drive/root:/Bilder/Eigene Aufnahmen:/children'
response = requests.get(request_url, headers=headers)
if response.status_code != 200:
    print(f"获取文件列表失败: {response.status_code} - {response.text}")
    exit()

files = response.json().get('value', [])
print(f"共找到 {len(files)} 个文件")

### 2. 遍历下载每个文件
for file in files:
    file_id = file['id']
    file_name = file['name']
    file_size = file.get('size', '未知')
    
    print(f"\n准备下载: {file_name} (大小: {file_size} bytes)")
    
    # 构造下载端点
    download_url = f"https://graph.microsoft.com/v1.0/me/drive/items/{file_id}/content"
    download_response = requests.get(download_url, headers=headers)
    
    if download_response.status_code == 200:
        # 保存文件到本地
        with open(file_name, 'wb') as f:
            f.write(download_response.content)
        print(f"✅ 成功下载文件: {file_name}")
    else:
        print(f"❌ 下载失败,状态码: {download_response.status_code},错误信息: {download_response.text}")

额外说明

  • 你的权限配置是正确的:Files.ReadWrite.All权限已经足够读取和下载个人OneDrive中的所有文件
  • 这种方式比直接使用临时downloadUrl更稳定,因为它完全依赖你通过MSAL获取的access token,不需要依赖浏览器会话的Cookie
  • 如果需要下载大文件,还可以使用Graph API的分段下载功能(通过Range请求头),避免一次性加载大文件到内存中

备注:内容来源于stack exchange,提问作者Andare

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 19:54:34