OpenXml、NPOI、EPPlus、Spire.Office组件对EXCEL ole对象附件的支持

OpenXml、NPOI、EPPlus、Spire.Office 对EXCEL插入附件的读取支持情况(比如插入ZIP文件)

这些主流Excel操作库对插入附件(如ZIP文件)的支持情况如下:

📊 支持情况对比

库名称 版本 附件读取支持 实现方式 备注
OpenXml 2.20+ ✅ 完全支持 直接操作OLE对象 最底层,最灵活
NPOI 2.7+ ✅ 支持 通过OLE对象访问 需要额外处理
EPPlus 5.8+ ⚠️ 有限支持 通过OLE对象 商业版支持更好
Spire.Office 13.8+ ✅ 支持 内置方法 商业库,功能完整

🔧 各库具体实现

1. OpenXml SDK - 最底层支持

cs 复制代码
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

public void ExtractAttachments(string filePath, string outputDir)
{
    using (var spreadsheet = SpreadsheetDocument.Open(filePath, false))
    {
        var workbookPart = spreadsheet.WorkbookPart;
        
        // 获取所有OLE对象
        foreach (var oleObject in workbookPart.OleObjectsPart?.OleObjects.Elements<OleObject>())
        {
            var objectId = oleObject.Id.Value;
            var embeddedObjectPart = (EmbeddedObjectPart)workbookPart.GetPartById(objectId);
            
            // 保存附件
            using (var stream = embeddedObjectPart.GetStream())
            {
                var fileName = $"attachment_{objectId}.bin";
                File.WriteAllBytes(Path.Combine(outputDir, fileName), ReadStream(stream));
            }
        }
    }
}

private byte[] ReadStream(Stream stream)
{
    using (var memoryStream = new MemoryStream())
    {
        stream.CopyTo(memoryStream);
        return memoryStream.ToArray();
    }
}

2. NPOI - 需要额外处理

cs 复制代码
using NPOI.XSSF.UserModel;
using NPOI.SS.UserModel;

public void ExtractAttachmentsNPOI(string filePath, string outputDir)
{
    using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
    {
        var workbook = new XSSFWorkbook(fs);
        var xssfWorkbook = (XSSFWorkbook)workbook;
        
        // 获取所有嵌入对象
        var package = xssfWorkbook.GetPackage();
        foreach (var partName in package.GetPartsByName("/xl/embeddings/.*"))
        {
            var part = package.GetPart(partName);
            using (var stream = part.GetInputStream())
            {
                var fileName = Path.GetFileName(partName.Name);
                File.WriteAllBytes(Path.Combine(outputDir, fileName), ReadStream(stream));
            }
        }
    }
}

3. EPPlus - 商业版支持更好

cs 复制代码
using OfficeOpenXml;

public void ExtractAttachmentsEPPlus(string filePath, string outputDir)
{
    ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
    
    using (var package = new ExcelPackage(new FileInfo(filePath)))
    {
        // EPPlus 5.8+ 商业版支持
        var workbook = package.Workbook;
        
        // 通过自定义方式访问OLE对象
        foreach (var worksheet in workbook.Worksheets)
        {
            var drawings = worksheet.Drawings;
            foreach (var drawing in drawings)
            {
                if (drawing is ExcelOleObjectDrawing oleObject)
                {
                    // 商业版功能
                    var content = oleObject.Content;
                    if (content != null)
                    {
                        File.WriteAllBytes(Path.Combine(outputDir, $"ole_{oleObject.Name}.bin"), content);
                    }
                }
            }
        }
    }
}

4. Spire.Office - 最便捷

cs 复制代码
using Spire.Xls;

public void ExtractAttachmentsSpire(string filePath, string outputDir)
{
    Workbook workbook = new Workbook();
    workbook.LoadFromFile(filePath);
    
    // 直接获取所有OLE对象
    foreach (Worksheet sheet in workbook.Worksheets)
    {
        foreach (Spire.Xls.OleObject oleObject in sheet.OleObjects)
        {
            // 获取附件数据
            byte[] data = oleObject.Data;
            string extension = GetFileExtension(oleObject.ObjectType);
            
            File.WriteAllBytes(Path.Combine(outputDir, 
                $"attachment_{sheet.Name}_{oleObject.Location.Row}_{oleObject.Location.Column}{extension}"), 
                data);
        }
    }
}

private string GetFileExtension(OleObjectType objectType)
{
    switch (objectType)
    {
        case OleObjectType.Package: return ".zip";
        case OleObjectType.AcrobatDocument: return ".pdf";
        case OleObjectType.WordDocument: return ".doc";
        default: return ".bin";
    }
}

📋 功能对比详情

OpenXml SDK

  • 优点: 最底层控制,支持所有附件类型

  • 缺点: 代码复杂,需要深入了解OOXML结构

  • 适用: 需要完全控制的高级场景

NPOI

  • 优点: 开源免费,支持基本附件操作

  • 缺点: API不够直观,需要手动处理Package

  • 适用: Java/.NET跨平台项目

EPPlus

  • 优点: API友好,性能优秀

  • 缺点: 免费版附件功能有限,商业版较贵

  • 适用: 简单Excel操作,商业项目

Spire.Office

  • 优点: 功能完整,API简单易用

  • 缺点: 商业收费,免费版有限制

  • 适用: 企业级应用,需要快速开发

🎯 推荐选择

  1. 完全免费 → NPOI

  2. 企业项目 → Spire.Office

  3. 底层控制 → OpenXml SDK

  4. 已有EPPlus → 升级到商业版

⚠️ 注意事项

  • 附件可能存储在/xl/embeddings//xl/oleObjects/路径

  • ZIP文件通常作为OLE Package对象插入

  • 需要处理不同的内容类型(MIME types)

  • 注意内存使用,大附件需要流式处理

根据你的具体需求和技术栈选择合适的库。

相关推荐
SEO-狼术20 小时前
Detect Trends with Compact In-Cell Visuals
.net
泥菩萨^_^21 小时前
【每天认识一个漏洞】React 和 Next.js RCE漏洞
前端·javascript·react.js
1024肥宅21 小时前
JavaScript常用设计模式完整指南
前端·javascript·设计模式
董世昌4121 小时前
js怎样控制浏览器前进、后退、页面跳转?
开发语言·前端·javascript
走,带你去玩21 小时前
uniapp live-pusher + 腾讯云直播
前端·javascript·uni-app
徐同保21 小时前
electron打包项目
前端·javascript·electron
Maybyy21 小时前
如何在项目里面添加一个可以左右翻动并显示指定日期的日历
前端·vue.js
赵庆明老师21 小时前
.NET 日志和监控
.net
柯南二号21 小时前
【大前端】【Android】用 Python 脚本模拟点击 Android APP —— 全面技术指南
android·前端·python
Arvin_Rong21 小时前
前端动态 API 生成与封装:前端 API 调用的一种思路
前端