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

如何使用Node.js下载OneDrive共享文件?Azure认证尝试失败

解决Node.js下载OneDrive共享文件的方案

核心问题说明

你用的客户端凭证模式(Client Credentials Flow)是服务到服务的认证逻辑,无法访问绑定个人账号权限的OneDrive共享文件——这类文件的访问权限基于你的个人身份,而非Azure应用本身的身份。OAuth2认证失败大概率是选错了授权流程,应该改用**授权码授权流程(Authorization Code Flow)**来模拟个人用户身份获取权限。

步骤1:调整Azure应用配置

  • 在Azure门户的应用注册页面,进入「身份验证」模块,添加Web应用/单页应用类型的重定向URI(示例:http://localhost:3000/redirect)
  • 切换到「API权限」,添加Files.Read.All、Sites.Read.All这两个委托权限(注意不是应用权限),完成后点击「授予管理员同意」(针对租户账号)

步骤2:用@azure/msal-node实现授权码流程

以下是完整可运行的代码示例,先启动本地服务引导用户完成授权,再通过授权码获取令牌,最后调用Graph API批量下载文件:

const msal = require('@azure/msal-node');
const axios = require('axios');
const fs = require('fs');
const http = require('http');
const path = require('path');

// MSAL基础配置
const config = {
    auth: {
        clientId: '你的Azure应用客户端ID',
        authority: 'https://login.microsoftonline.com/你的租户ID',
        clientSecret: '你的Azure应用密钥'
    }
};

const pca = new msal.PublicClientApplication(config);
const REDIRECT_URI = 'http://localhost:3000/redirect';
const SCOPES = ['Files.Read.All', 'Sites.Read.All', 'offline_access'];
const DOWNLOAD_DIR = './onedrive_downloads';

// 创建本地下载目录
if (!fs.existsSync(DOWNLOAD_DIR)) {
    fs.mkdirSync(DOWNLOAD_DIR);
}

// 启动本地HTTP服务处理授权回调
const server = http.createServer(async (req, res) => {
    // 处理授权回调
    if (req.url.startsWith('/redirect')) {
        const urlParams = new URL(req.url, `http://${req.headers.host}`).searchParams;
        const authCode = urlParams.get('code');

        if (!authCode) {
            res.end('未获取到授权码,请重新尝试');
            return;
        }

        try {
            // 用授权码交换访问令牌
            const tokenResult = await pca.acquireTokenByCode({
                code: authCode,
                scopes: SCOPES,
                redirectUri: REDIRECT_URI
            });
            const accessToken = tokenResult.accessToken;

            // 替换为你的共享文件夹ID
            const sharedFolderId = '共享文件夹的ID';
            // 获取文件夹下所有文件列表
            const filesRes = await axios.get(
                `https://graph.microsoft.com/v1.0/me/drive/items/${sharedFolderId}/children`,
                { headers: { Authorization: `Bearer ${accessToken}` } }
            );

            // 批量下载文件
            for (const item of filesRes.data.value) {
                if (item.file) {
                    const fileStream = await axios.get(
                        `https://graph.microsoft.com/v1.0/me/drive/items/${item.id}/content`,
                        { headers: { Authorization: `Bearer ${accessToken}` }, responseType: 'stream' }
                    );
                    const savePath = path.join(DOWNLOAD_DIR, item.name);
                    fileStream.data.pipe(fs.createWriteStream(savePath));
                    console.log(`已完成下载:${item.name}`);
                }
            }

            res.end('所有文件下载完成,可关闭此页面');
            server.close();
        } catch (err) {
            console.error('操作失败:', err.message);
            res.end(`出错了:${err.message}`);
        }
    } else {
        // 引导用户跳转至微软授权页面
        const authUrl = await pca.getAuthCodeUrl({
            scopes: SCOPES,
            redirectUri: REDIRECT_URI
        });
        res.writeHead(302, { Location: authUrl });
        res.end();
    }
});

server.listen(3000, () => {
    console.log('请访问 http://localhost:3000 完成授权登录');
});

步骤3:获取共享文件夹ID的方法

如果不知道共享文件夹的ID,可通过两种方式获取:

  • 打开共享链接,在浏览器控制台执行window.location.pathname,提取路径中的资源ID;
  • 调用Graph API搜索接口:发送GET请求到https://graph.microsoft.com/v1.0/me/drive/search(q='共享文件夹名称'),在返回结果中找到对应文件夹的id字段。

关键注意事项

  • 必须使用委托权限,应用权限无法访问用户个人OneDrive的共享内容;
  • 授权码流程需要用户手动登录一次,获取到的refresh token可用于后续刷新访问令牌,无需重复登录;
  • 确保本地下载目录已创建,否则会出现文件写入失败的错误。

内容的提问来源于stack exchange,提问作者Sajib Hossain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 07:02:27