C#通过SharePoint API操作文件/文件夹:文件夹定位问题求助
我来帮你理清SharePoint的结构逻辑,修正你的代码,让你能顺利实现文件夹创建、文件上传下载这些功能。
先搞懂SharePoint文档库的核心结构
首先要区分视图页面和实际存储路径:
- 你提到的
AllItems.aspx是文档库的视图页面,用来展示库内的内容,但它本身不是文件夹,不能用这个页面的路径去获取实际的文件/文件夹。 - 你说的
Kontrakter是一个文档库(属于SharePoint里的List类型,专门用于存储文件),它的根文件夹就是库本身,所有文件和子文件夹都存在这个根文件夹下。
修正ClientContext代码,正确获取文件夹内容
你的代码里存在几个问题:创建了多个不必要的ClientContext、没有正确执行ExecuteQuery()、混淆了页面路径和存储路径。下面是优化后的完整代码:
using Microsoft.SharePoint.Client; using System.IO; // 注意:这里要指向具体的子站点URL,比如你的sites/yy string siteUrl = "https://xx.sharepoint.com/sites/yy"; using (ClientContext cxt = new ClientContext(siteUrl)) { // 确保你的GetCredentials返回正确的凭据(针对SharePoint Online,推荐用SharePointOnlineCredentials) cxt.Credentials = GetCredentials(); // 1. 获取名为"Kontrakter"的文档库 List docLibrary = cxt.Web.Lists.GetByTitle("Kontrakter"); // 先加载库的根文件夹 cxt.Load(docLibrary, lib => lib.RootFolder); cxt.ExecuteQuery(); // 2. 获取根文件夹的文件和子文件夹 Folder rootFolder = docLibrary.RootFolder; cxt.Load(rootFolder, folder => folder.Files, // 加载文件夹内的所有文件 folder => folder.Folders); // 加载文件夹内的所有子文件夹 cxt.ExecuteQuery(); // 输出根文件夹的内容信息 Console.WriteLine($"Kontrakter根文件夹共有 {rootFolder.Files.Count} 个文件"); Console.WriteLine("子文件夹列表:"); foreach (Folder subFolder in rootFolder.Folders) { Console.WriteLine($"- {subFolder.Name}"); } // 3. 如果要获取指定子文件夹(比如你提到的Forms) string formsFolderRelativeUrl = $"/sites/yy/Kontrakter/Forms"; Folder formsFolder = cxt.Web.GetFolderByServerRelativeUrl(formsFolderRelativeUrl); cxt.Load(formsFolder, f => f.Files); cxt.ExecuteQuery(); Console.WriteLine($"Forms文件夹共有 {formsFolder.Files.Count} 个文件"); }
代码关键点说明:
- ClientContext指向正确的站点:必须是具体的子站点URL(如
https://xx.sharepoint.com/sites/yy),而不是根站点或页面URL。 - 必须执行ExecuteQuery():SharePoint Client Object Model是延迟加载的,调用
Load()后必须执行ExecuteQuery()才能真正从服务器获取数据。 - ServerRelativeUrl格式:路径要从站点根开始,比如
/sites/yy/Kontrakter/Forms,而不是页面的AbsolutePath。
正确的REST API调用方式
你之前的API路径有误,正确的调用应该针对具体站点和库:
获取Kontrakter根文件夹的文件
GET https://xx.sharepoint.com/sites/yy/_api/Web/GetFolderByServerRelativeUrl('/sites/yy/Kontrakter')/Files
通过文档库RootFolder获取文件
GET https://xx.sharepoint.com/sites/yy/_api/Web/Lists/GetByTitle('Kontrakter')/RootFolder/Files
获取Forms子文件夹的文件
GET https://xx.sharepoint.com/sites/yy/_api/Web/GetFolderByServerRelativeUrl('/sites/yy/Kontrakter/Forms')/Files
补充:常用操作示例(创建文件夹、上传/下载文件)
创建子文件夹
// 在Kontrakter根文件夹下创建名为"NewProjectFolder"的子文件夹 Folder newFolder = rootFolder.Folders.Add("NewProjectFolder"); cxt.ExecuteQuery(); Console.WriteLine($"新创建的文件夹路径:{newFolder.ServerRelativeUrl}");
上传文件到文件夹
string localFilePath = @"C:\Documents\test_contract.pdf"; using (FileStream fs = new FileStream(localFilePath, FileMode.Open)) { FileCreationInformation fileInfo = new FileCreationInformation(); fileInfo.ContentStream = fs; fileInfo.Url = Path.GetFileName(localFilePath); // 要上传的文件名 fileInfo.Overwrite = true; // 如果文件已存在则覆盖 // 上传到根文件夹,也可以替换成指定子文件夹 Microsoft.SharePoint.Client.File uploadedFile = rootFolder.Files.Add(fileInfo); cxt.ExecuteQuery(); Console.WriteLine($"上传成功,文件URL:{uploadedFile.ServerRelativeUrl}"); }
下载文件
// 从根文件夹下载指定文件 Microsoft.SharePoint.Client.File targetFile = rootFolder.Files.GetByUrl("test_contract.pdf"); cxt.Load(targetFile); cxt.ExecuteQuery(); // 打开文件流并保存到本地 FileInformation fileStream = Microsoft.SharePoint.Client.File.OpenBinaryDirect(cxt, targetFile.ServerRelativeUrl); string savePath = @"C:\Downloads\downloaded_contract.pdf"; using (FileStream fs = new FileStream(savePath, FileMode.Create)) { fileStream.Stream.CopyTo(fs); } Console.WriteLine("文件下载完成");
最后总结几个坑点
- 不要混淆视图页面(AllItems.aspx)和实际存储路径,页面只是展示用的,不是存储位置。
- 确保凭据正确:如果是SharePoint Online,必须使用
SharePointOnlineCredentials而不是普通的NetworkCredential。 - 所有需要从服务器获取的属性,必须先通过
Load()指定,再执行ExecuteQuery()才能访问。
内容的提问来源于stack exchange,提问作者user3122410
相关产品推荐
相关产品推荐

