使用SpreadsheetDocument.Open()读取带MFA的SharePoint Excel文件报错如何解决?
问题原因
SpreadsheetDocument.Open() 无法直接处理SharePoint Online的身份验证流程(尤其是MFA),你在浏览器中使用的URL是经过身份验证后的临时访问链接,代码中直接使用该URL时没有携带有效的身份凭证,因此会抛出“Could not find document”异常。
可行解决方案
方案1:通过Microsoft Graph API获取文件流
利用Graph API获取文件的二进制内容流,再传入SpreadsheetDocument.Open()处理,步骤如下:
- 在Azure AD中注册应用,添加Files.Read(委托权限)并授予管理员同意。
- 使用MSAL库获取支持MFA的访问令牌。
- 调用Graph API获取文件内容流,再打开处理。
示例代码:
using Microsoft.Identity.Client; using DocumentFormat.OpenXml.Packaging; using System.Net.Http; using System.IO; // 1. 获取MFA令牌 var clientId = "你的Azure应用客户端ID"; var tenantId = "你的租户ID"; var scopes = new[] { "https://graph.microsoft.com/Files.Read" }; var publicClientApp = PublicClientApplicationBuilder .Create(clientId) .WithTenantId(tenantId) .Build(); var result = await publicClientApp.AcquireTokenInteractive(scopes).ExecuteAsync(); var accessToken = result.AccessToken; // 2. 调用Graph API获取文件流(替换为你的文件ID和站点ID) var fileUrl = "https://graph.microsoft.com/v1.0/sites/{site-id}/drive/items/{file-id}/content"; using var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken); var stream = await httpClient.GetStreamAsync(fileUrl); // 3. 用SpreadsheetDocument只读打开流 using var spreadsheetDoc = SpreadsheetDocument.Open(stream, false); // 后续只读操作,比如读取工作表内容 var workbookPart = spreadsheetDoc.WorkbookPart; var sheet = workbookPart.Workbook.Sheets.FirstOrDefault(); // ... 其他逻辑
方案2:使用PnP Framework简化SharePoint访问
PnP Framework内置了对MFA的支持,无需手动处理令牌,步骤如下:
- 安装
PnP.FrameworkNuGet包。 - 使用
PnPContext连接站点,获取文件流后处理。
示例代码:
using PnP.Framework; using DocumentFormat.OpenXml.Packaging; using System.IO; // 1. 连接SharePoint站点(会自动触发MFA验证) var siteUrl = "https://xxxx.sharepoint.com/sites/XXXXTeam"; using var context = await PnPContextFactory.CreateAsync(siteUrl); // 2. 获取文件并下载流 var file = await context.Web.GetFileByServerRelativeUrl("/sites/XXXXTeam/Shared Documents/General/Test Files/excel.xlsx"); var stream = new MemoryStream(); await file.DownloadAsync(stream); stream.Position = 0; // 重置流位置 // 3. 只读打开Excel文件 using var spreadsheetDoc = SpreadsheetDocument.Open(stream, false); // 执行只读操作 // ...
关键注意事项
- 不要直接使用浏览器中的URL,该URL是经过重定向的临时链接,不适合代码调用。
- 无论哪种方案,都需要确保应用或账号拥有目标文件的只读权限。
- 使用
SpreadsheetDocument.Open()时,第二个参数设为false表示只读模式,避免意外修改文件。
内容的提问来源于stack exchange,提问作者Moshe Raab
相关产品推荐
相关产品推荐

