C#提取SharePoint在线PDF文本失败,请求技术解决方案
你遇到的InvalidPdfException: 'PDF header signature not found.'本质是你的请求没有成功拿到SharePoint上的PDF文件,反而获取到了其他内容(大概率是未授权的登录页面HTML),所以iTextSharp无法识别为合法PDF。浏览器保存的凭证是会话隔离的,代码没法直接复用,下面给你具体的解决思路和修复方案:
1. 先搞懂SharePoint的认证逻辑
你当前用的CredentialCache.DefaultCredentials或NetworkCredential只适用于简单的Windows NTML认证,但现代SharePoint(尤其是Online/M365版本)用的是OAuth/ADFS等更复杂的认证机制,普通HttpWebRequest没法直接绕过。
2. 针对不同SharePoint环境的修复方案
方案一:SharePoint Online(M365)推荐用CSOM
这是最稳定的方式,先安装NuGet包Microsoft.SharePointOnline.CSOM,然后用以下代码获取文件流并提取文本:
using Microsoft.SharePoint.Client; using System.IO; using System.Security; using iTextSharp.text.pdf; using iTextSharp.text.pdf.parser; public static string ExtractSharePointOnlinePdfText(string siteUrl, string serverRelativeFilePath, string userName, string password) { string extractedText = string.Empty; // 安全存储密码 var securePassword = new SecureString(); foreach (char c in password) { securePassword.AppendChar(c); } using (var context = new ClientContext(siteUrl)) { // 配置SharePoint Online认证 context.Credentials = new SharePointOnlineCredentials(userName, securePassword); // 获取目标文件 var file = context.Web.GetFileByServerRelativeUrl(serverRelativeFilePath); context.Load(file); context.ExecuteQuery(); // 获取文件流并提取文本 using (var pdfStream = file.OpenBinaryStream()) { using (var reader = new PdfReader(pdfStream)) { for (int page = 1; page <= reader.NumberOfPages; page++) { extractedText += PdfTextExtractor.GetTextFromPage(reader, page); } } } } return extractedText; }
注意:
serverRelativeFilePath是文件在站点内的相对路径,比如/Documents/MyPrivateFile.pdf
方案二:本地SharePoint服务器(On-Premises)调整HttpWebRequest认证
如果是本地部署的SharePoint,试试NTLM认证并开启自动解压:
public static string pdfTX(string path, string userName, string password, string domain) { CookieContainer cookieJar = new CookieContainer(); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(path); // 配置NTLM认证 request.Credentials = new NetworkCredential(userName, password, domain); request.PreAuthenticate = true; // 开启Gzip解压,SharePoint可能返回压缩内容 request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; request.UserAgent = @"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36"; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (Stream stream = response.GetResponseStream()) { // 先调试:把流保存到本地,确认是不是PDF // using (FileStream fs = new FileStream("test.pdf", FileMode.Create)) { stream.CopyTo(fs); } string textPDF = string.Empty; PdfReader reader = new PdfReader(stream); for (int page = 1; page <= reader.NumberOfPages; page++) { textPDF += PdfTextExtractor.GetTextFromPage(reader, page); } reader.Close(); return textPDF; } }
务必确保
path是PDF的直接下载URL,不是SharePoint的预览页面URL(预览页是HTML,不是PDF流)。
3. 关键调试步骤
如果还是出错,先把请求返回的流保存成本地文件:
using (FileStream fs = new FileStream("response_content.html", FileMode.Create)) { stream.CopyTo(fs); }
打开这个文件,如果是登录页面、权限提示或HTML错误页,就说明认证肯定没通过,需要调整认证方式;如果是乱码,可能是没开启解压。
内容的提问来源于stack exchange,提问作者Kugelkopf

