csom适用于.net framework环境且需app-only权限的后台上传,须注册app获取clientid/secret并用tokenhelper认证;graph api适合.net core+msal场景,小文件≤4mb用put,大文件需createuploadsession分块上传。

CSOM上传文件到SharePoint文档库(.NET Framework 4.7.2+)
CSOM适合已部署在Windows Server或传统.NET Framework环境、且有SharePoint Online管理员权限配置App-Only访问的场景。它不依赖用户登录态,适合后台服务调用。
关键点:必须先注册SharePoint App并获取ClientId和ClientSecret,再用SharePointOnlineCredentials或更安全的ClientContext + TokenHelper方式认证。直接传用户名密码在现代身份验证下会失败。
- 引用NuGet包:
Microsoft.SharePointOnline.CSOM(v16.1.23919.12000+) - 目标URL需是文档库根路径,例如:
https://contoso.sharepoint.com/sites/team/Shared%20Documents - 上传前检查父文件夹是否存在,CSOM不会自动创建嵌套路径,
context.Web.GetFolderByServerRelativeUrl()抛异常需自行捕获并递归创建 - 大文件(>10MB)建议改用
File.SaveBinaryDirect()或分块上传(StartUpload/ContinueUpload/FinishUpload),否则易超时
var ctx = new ClientContext("https://contoso.sharepoint.com/sites/team");
ctx.Credentials = new SharePointOnlineCredentials("user@contoso.com", securePassword);
var fileCreationInfo = new FileCreationInformation
{
Content = File.ReadAllBytes(@"C:\temp\report.pdf"),
Url = "report.pdf",
Overwrite = true
};
var docs = ctx.Web.Lists.GetByTitle("Shared Documents");
var uploadFile = docs.RootFolder.Files.Add(fileCreationInfo);
ctx.Load(uploadFile);
ctx.ExecuteQuery();
Graph API上传小文件(≤4MB)到SharePoint文档库
Graph API更适合.NET Core/.NET 5+项目,且已有Azure AD应用注册(类型为“Web”)、已授Files.ReadWrite.All或Sites.Write.All权限。它统一了OneDrive和SharePoint的文件操作语义。
注意:Graph不直接暴露“文档库路径”,而是通过siteId + driveId定位——driveId对应文档库,需先用/sites/{site-id}/drives查出目标文档库的id,再调/drives/{drive-id}/root:/{filename}:/content上传。
- 小文件(≤4MB)用
PATCH /drives/{id}/items/{item-id}/content最简;无item-id时用PUT /drives/{id}/root:/{filename}:/content - 必须使用
HttpClient带Bearer Token请求,Token需由Microsoft.Identity.Client(MSAL)获取,不能硬编码 - 响应状态码
201 Created表示成功,404大概率是driveId错或路径中文件夹不存在(Graph不自动建中间目录) - 中文文件名需URL编码,否则
400 Bad Request
var url = $"https://graph.microsoft.com/v1.0/drives/{driveId}/root:/report.pdf:/content";
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var content = new ByteArrayContent(File.ReadAllBytes(@"C:\temp\report.pdf"));
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
var resp = await client.PutAsync(url, content);
Graph分块上传大文件(>4MB)到SharePoint
超过4MB必须走createUploadSession流程,否则返回413 Payload Too Large。整个过程分三步:申请会话 → 分片上传 → 提交完成。会话有效期默认3小时,但每片上传后需更新过期时间。
容易漏掉的细节:每次PUT分片必须带Content-Range头,格式如bytes 0-1048575/5242880,且最后一片的range末尾值必须等于总大小减一;若某片失败,需重传该片,不能跳过。
- 第一步:
POST /drives/{id}/root:/{filename}:/createUploadSession,Body为空或含{"item": {"@microsoft.graph.conflictBehavior": "replace"}} - 第二步:对返回的
uploadUrl发PUT,Header加Content-Range和Content-Length,Body为当前分片字节 - 第三步:最后一次
PUT成功后,Graph自动返回完整driveItem对象,无需额外提交 - .NET中推荐用
Stream分段读取本地文件,避免File.ReadAllBytes()爆内存
CSOM vs Graph:选哪个?关键看这三点
没有绝对优劣,取决于你的运行环境、权限模型和文件大小分布。
- 用CSOM:已有SharePoint App ID/Secret、服务长期运行、需上传>100MB文件(CSOM分块API更稳定)、或必须兼容SharePoint Server 2019(Graph不支持)
- 用Graph:项目基于.NET Core、已用MSAL做统一认证、需同时操作OneDrive和SharePoint、或前端已调Graph(后端复用Token逻辑)
- 混合用:常见于迁移场景——用Graph查元数据(快)、用CSOM传超大附件(稳)。但要注意两个API的权限粒度不同,
Sites.FullControl.All不等价于CSOM的FullControl站点权限
最常被忽略的是权限同步延迟:Azure AD应用授权后,SharePoint端可能要等15分钟才生效,期间Graph返回403 Forbidden、CSOM报Access denied,别急着改代码,先等一等。










