如何无交互程序化提取SharePoint下载的归档格式OneNote文本?
我之前也碰到过一模一样的问题——从SharePoint下载的OneNote归档文件总能把IFilter搞罢工,毕竟这种格式是打包后的静态归档,不是原生可编辑的OneNote笔记本格式。下面给你几个实用的方案,按推荐优先级排序:
1. 直接从SharePoint获取内容,跳过下载归档文件
这是最根本的解决思路:既然问题出在下载的归档文件上,那我们直接绕开它,用API读取SharePoint上的OneNote内容。
用Microsoft Graph API(首推)
SharePoint的OneNote内容完全可以通过Graph API直接获取,不需要下载任何文件,彻底避开格式问题。给你个C#的简单示例:
using Microsoft.Graph; using Azure.Identity; using HtmlAgilityPack; // 用来解析HTML提取纯文本 var graphClient = new GraphServiceClient(new ClientSecretCredential( "你的租户ID", "你的客户端ID", "你的客户端密钥", new TokenCredentialOptions())); // 替换成你的SharePoint站点ID var siteId = "your-site-id"; // 获取站点下的所有笔记本 var notebooks = await graphClient.Sites[siteId].Onenote.Notebooks.Request().GetAsync(); foreach (var notebook in notebooks) { // 获取笔记本的分区 var sections = await graphClient.Sites[siteId].Onenote.Notebooks[notebook.Id].Sections.Request().GetAsync(); foreach (var section in sections) { // 获取分区的所有页面 var pages = await graphClient.Sites[siteId].Onenote.Sections[section.Id].Pages.Request().GetAsync(); foreach (var page in pages) { // 获取页面的HTML内容 var pageHtml = await graphClient.Sites[siteId].Onenote.Pages[page.Id].Content.Request().GetAsync(); // 用HtmlAgilityPack提取纯文本 var doc = new HtmlDocument(); doc.LoadHtml(pageHtml); string pageText = doc.DocumentNode.InnerText; // 这里可以处理提取到的文本 } } }
这个方法不需要安装OneNote客户端,也不用处理本地文件格式问题,完全云端操作,省心又高效。
2. 解析OneNote归档文件的ZIP结构(纯.NET代码,无需Office组件)
你下载的归档格式.one(其实通常是.onepkg后缀,可能SharePoint下载时自动重命名了)本质就是个ZIP压缩包,里面藏着OneNote的XML结构文件。我们可以直接解压后解析XML提取文本,完全不需要依赖Office或者IFilter。
示例代码:
using System.IO.Compression; using System.Xml.Linq; string archivePath = @"d:\Note.one"; string extractedText = string.Empty; using (ZipArchive archive = ZipFile.OpenRead(archivePath)) { // 遍历所有OneNote页面XML文件(路径通常是OneNote/Page*.xml) foreach (ZipArchiveEntry entry in archive.Entries) { if (entry.FullName.StartsWith("OneNote/Page") && entry.Name.EndsWith(".xml")) { using (var reader = new StreamReader(entry.Open())) { XDocument doc = XDocument.Load(reader); // OneNote XML的命名空间必须指定,不然找不到节点 XNamespace ns = "http://schemas.microsoft.com/office/onenote/2013/onenote"; // 提取所有<T>节点的文本内容(这是OneNote存储文本的核心节点) var textNodes = doc.Descendants(ns + "T"); foreach (var node in textNodes) { extractedText += node.Value + Environment.NewLine; } } } } } // extractedText就是提取到的纯文本
这个方法完全无外部依赖,只要是.NET环境就能跑,速度还快。
3. 无交互转换归档格式为可编辑OneNote(改进互操作代码)
如果你还是想用互操作,但不想转PDF,可以直接把归档格式转换为可编辑的.one文件,而且能后台无交互运行:
using Microsoft.Office.Interop.OneNote; IApplication app = new Application(); app.Visible = false; // 关键设置:后台运行,不弹出OneNote窗口 try { string originalPath = @"d:\Note.one"; string convertedPath = @"d:\ConvertedNote.one"; // 打开归档文件 app.OpenHierarchy(originalPath, string.Empty, out string hierarchyId, CreateFileType.cftNone); // 同步确保内容加载完成 app.SyncHierarchy(hierarchyId); // 导出为可编辑的OneNote格式(不是PDF!) app.Publish(hierarchyId, convertedPath, PublishFormat.pfOneNote); // 现在ConvertedNote.one就可以用IFilter正常读取了 } finally { app.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(app); }
这个方法需要安装OneNote客户端,但全程无用户交互,比转PDF高效得多。
关于SharePoint下载避免归档文件的补充
如果你一定要下载文件,要注意:SharePoint里的OneNote笔记本是作为文档库存在的,不是单个文件。你应该用CSOM下载整个笔记本的文件结构,而不是下载单个归档文件。比如用CSOM获取笔记本的所有关联文件,逐个下载,这样得到的就是原生可编辑的OneNote文件,不会出现归档格式的问题。
内容的提问来源于stack exchange,提问作者DevDaniel




