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

如何在不使用REST API的情况下用C#从SharePoint Online下载文件?

SharePoint Online共享链接文件下载问题

我尝试仅通过SharePoint Online的共享文档链接下载文件,示例链接:https://ourcompanysite.sharepoint.com/:p:/s/CP/EUo3_Xs4SKtAsSZCZxJBXyQBAFRhL3pXz7-sM_F-RTyzcA?e=4%3a85JGQ2&at=9

使用System.Net.WebClient实现的代码如下:

using (WebClient loWC = new System.Net.WebClient())
{
    string lsFileName = "https://companysite.sharepoint.com/:p:/s/CP/EUo3_Xs4SKzcA?e=4%3a85JGQ2&at=9";
    Uri loURI = new Uri(lsFileName);
    loWC.Credentials = new NetworkCredential("myuser@company.com.au", "Pass123");
    byte[] loData = null;
    ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
    ServicePointManager.DefaultConnectionLimit = 9999;
    byte[] loData = loWC.DownloadData(loURI);         
}

执行loWC.DownloadData时触发403 Forbidden错误,但我确实拥有该站点的访问权限。

我的疑问:

  1. 当用户名是邮箱格式(无单独域/用户名)时,这种凭证传递方式是否可行?
  2. 是否可以不依赖SharePoint REST API,仅通过这种方式下载文件(或获取内容)?因为我不清楚文档库的完整路径和文件名。

问题解答

1. 邮箱格式用户名的凭证传递问题

直接用NetworkCredential传递邮箱和密码的方式不可行。SharePoint Online采用OAuth 2.0或Azure AD身份验证机制,传统的NetworkCredential是针对NTLM/Kerberos等Windows本地身份验证设计的,无法适配云环境的身份验证流程。即使输入正确的邮箱和密码,也会被SharePoint Online的身份验证系统拒绝,导致403错误。

2. 不使用REST API通过共享链接下载文件的方案

可以实现,但需要先将共享链接转换为直接下载链接,并使用适配云环境的身份验证方式,具体方案如下:

步骤1:转换共享链接为直接下载链接

SharePoint的权限共享链接(如:p:/格式)需要转换为指向文件内容的直接URL,转换规则:

  • 将链接中的:p:/替换为:u:/
  • 在链接末尾添加&download=1

示例链接转换后为:
https://ourcompanysite.sharepoint.com/:u:/s/CP/EUo3_Xs4SKtAsSZCZxJBXyQBAFRhL3pXz7-sM_F-RTyzcA?e=4%3a85JGQ2&at=9&download=1

步骤2:使用正确的身份验证方式

放弃WebClient的NetworkCredential,改用以下两种主流方式处理身份验证并下载文件:

方案A:Microsoft Graph API(推荐)

通过Graph API的shares端点解析共享链接,直接获取文件内容:

using Microsoft.Graph;
using Azure.Identity;

var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "你的租户ID";
var clientId = "你的应用注册ID";
var clientSecret = "你的应用密钥";

var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);

// 编码共享链接
string encodedUrl = System.Web.HttpUtility.UrlEncode("https://ourcompanysite.sharepoint.com/:p:/s/CP/EUo3_Xs4SKtAsSZCZxJBXyQBAFRhL3pXz7-sM_F-RTyzcA?e=4%3a85JGQ2&at=9");
var sharedItem = await graphClient.Shares[$"u!{encodedUrl}"].Request().GetAsync();

// 获取文件内容流
var fileContentStream = await graphClient.Shares[$"u!{encodedUrl}"].DriveItem.Content.Request().GetAsync();
方案B:SharePoint CSOM

通过CSOM解析共享链接并下载文件,需先安装Microsoft.SharePointOnline.CSOM NuGet包:

using Microsoft.SharePoint.Client;
using System.Security;

using (var context = new ClientContext("https://ourcompanysite.sharepoint.com/sites/CP"))
{
    // 用户名密码验证(注:该方式已逐步被弃用,优先推荐应用权限)
    context.Credentials = new SharePointOnlineCredentials("myuser@company.com.au", ConvertToSecureString("Pass123"));
    
    // 通过共享链接获取文件对象
    var file = Web.GetFileByUrl(context, "https://ourcompanysite.sharepoint.com/:p:/s/CP/EUo3_Xs4SKtAsSZCZxJBXyQBAFRhL3pXz7-sM_F-RTyzcA?e=4%3a85JGQ2&at=9");
    context.Load(file);
    context.ExecuteQuery();
    
    // 下载文件内容
    var fileContentStream = file.OpenBinaryStream();
    context.ExecuteQuery();
}

// 辅助方法:将字符串转为SecureString
private static SecureString ConvertToSecureString(string password)
{
    var securePassword = new SecureString();
    foreach (char c in password)
    {
        securePassword.AppendChar(c);
    }
    return securePassword;
}

注意事项

  • 若没有应用权限(clientId/clientSecret),可临时使用用户名密码流,但该方式可能被租户禁用,长期来看优先采用应用权限。
  • 即使转换了下载链接,仍需正确的身份验证才能访问,否则仍会返回403错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:55:31