如何用C# Graph API在SharePoint文档库创建并上传含文件的文件夹
权限要求
确保你的应用已申请以下权限之一(根据实际场景选择,Delegated权限适合交互式场景,Application权限适合后台服务):
Files.ReadWrite.AllSites.ReadWrite.All
一、创建单个文件夹
实现代码
假设你已掌握目标SharePoint站点ID和文档库ID(若未知文档库ID,可通过站点路径先获取对应Drive对象),以下是创建文件夹的具体实现:
using Microsoft.Graph; using Microsoft.Graph.Models; public class SharePointOperations { private readonly GraphServiceClient _graphClient; // 注入已初始化的GraphServiceClient public SharePointOperations(GraphServiceClient graphClient) { _graphClient = graphClient; } /// <summary> /// 在SharePoint文档库指定路径下创建单个文件夹 /// </summary> /// <param name="siteId">SharePoint站点ID</param> /// <param name="documentLibraryId">文档库对应的Drive ID</param> /// <param name="parentFolderPath">父文件夹路径,根路径可传""或"/"</param> /// <param name="folderName">目标文件夹名称</param> /// <returns>创建完成的DriveItem对象</returns> public async Task<DriveItem> CreateSingleFolderAsync(string siteId, string documentLibraryId, string parentFolderPath, string folderName) { var newFolder = new DriveItem { Name = folderName, Folder = new Folder(), AdditionalData = new Dictionary<string, object> { {"@microsoft.graph.conflictBehavior", "rename"} // 冲突时自动重命名,可选值:fail/rename/replace } }; // 拼接父文件夹的请求路径 var parentItemPath = string.IsNullOrEmpty(parentFolderPath.Trim()) ? "root" : $"root:/{parentFolderPath.Trim('/')}"; return await _graphClient.Sites[siteId].Drives[documentLibraryId].Items[parentItemPath] .Children .Request() .AddAsync(newFolder); } }
关键说明
@microsoft.graph.conflictBehavior用于处理文件夹已存在的场景:fail:默认值,直接抛出异常rename:自动重命名为"FolderName 1"这类格式replace:覆盖现有文件夹
- 若不知道文档库ID,可通过站点域名+名称获取Drive列表:
var drives = await _graphClient.Sites["{your-site-domain}:/sites/{your-site-name}"].Drives.Request().GetAsync();
二、上传本地文件夹至文档库
实现思路
- 递归遍历本地文件夹的所有文件和子文件夹
- 在文档库中同步创建对应的文件夹结构
- 逐个上传本地文件到对应文档库路径
实现代码
/// <summary> /// 上传本地文件夹至SharePoint文档库指定路径 /// </summary> /// <param name="siteId">SharePoint站点ID</param> /// <param name="documentLibraryId">文档库Drive ID</param> /// <param name="targetLibraryPath">文档库内的目标根路径,如"/Documents/UploadedFiles"</param> /// <param name="localFolderPath">本地文件夹的绝对路径</param> public async Task UploadLocalFolderAsync(string siteId, string documentLibraryId, string targetLibraryPath, string localFolderPath) { if (!Directory.Exists(localFolderPath)) throw new DirectoryNotFoundException($"本地文件夹不存在:{localFolderPath}"); // 创建文档库中的目标根文件夹 var targetRootFolder = await CreateSingleFolderAsync(siteId, documentLibraryId, Path.GetDirectoryName(targetLibraryPath.Trim('/')), Path.GetFileName(targetLibraryPath.Trim('/'))); // 递归上传文件夹内容 await UploadFolderRecursiveAsync(siteId, documentLibraryId, targetRootFolder.Id, localFolderPath); } /// <summary> /// 递归处理文件夹内的文件和子文件夹 /// </summary> private async Task UploadFolderRecursiveAsync(string siteId, string documentLibraryId, string parentFolderId, string localFolderPath) { // 上传当前文件夹下的所有文件 foreach (var filePath in Directory.GetFiles(localFolderPath)) { var fileName = Path.GetFileName(filePath); using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); // 上传文件到指定父文件夹 await _graphClient.Sites[siteId].Drives[documentLibraryId].Items[parentFolderId] .ItemWithPath(fileName) .Content .Request() .PutAsync<DriveItem>(fileStream); } // 处理当前文件夹下的所有子文件夹 foreach (var subDirPath in Directory.GetDirectories(localFolderPath)) { var subDirName = Path.GetFileName(subDirPath); // 在文档库父文件夹下创建子文件夹 var subFolderItem = new DriveItem { Name = subDirName, Folder = new Folder() }; var subFolder = await _graphClient.Sites[siteId].Drives[documentLibraryId].Items[parentFolderId] .Children .Request() .AddAsync(subFolderItem); // 递归上传子文件夹内容 await UploadFolderRecursiveAsync(siteId, documentLibraryId, subFolder.Id, subDirPath); } }
关键说明
- 上传文件默认会覆盖同名文件,如需避免覆盖,可添加冲突处理头:
await _graphClient.Sites[siteId].Drives[documentLibraryId].Items[parentFolderId] .ItemWithPath(fileName) .Content .Request() .Header("@microsoft.graph.conflictBehavior", "rename") .PutAsync<DriveItem>(fileStream); - 若文件超过4MB,建议使用分块上传(通过
CreateUploadSession方法实现),上述代码适用于小文件场景。
使用示例
假设你的GraphHandler类提供了获取GraphServiceClient的方法,调用方式如下:
var graphClient = new GraphHandler().GetGraphClient(); var spOperations = new SharePointOperations(graphClient); // 创建单个文件夹 await spOperations.CreateSingleFolderAsync( siteId: "your-site-id", documentLibraryId: "your-drive-id", parentFolderPath: "/Documents", folderName: "NewProjectFolder"); // 上传本地文件夹 await spOperations.UploadLocalFolderAsync( siteId: "your-site-id", documentLibraryId: "your-drive-id", targetLibraryPath: "/Documents/UploadedLocalFiles", localFolderPath: @"C:\LocalFiles\MyFolder");
内容的提问来源于stack exchange,提问作者Ashish Prajapati
相关产品推荐
相关产品推荐

