You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何无交互程序化提取SharePoint下载的归档格式OneNote文本?

解决OneNote归档格式IFilter读取失败及无交互提取内容的方案

我之前也碰到过一模一样的问题——从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

火山引擎 最新活动