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简单易用
-
缺点: 商业收费,免费版有限制
-
适用: 企业级应用,需要快速开发
🎯 推荐选择
-
完全免费 → NPOI
-
企业项目 → Spire.Office
-
底层控制 → OpenXml SDK
-
已有EPPlus → 升级到商业版
⚠️ 注意事项
-
附件可能存储在
/xl/embeddings/
或/xl/oleObjects/
路径 -
ZIP文件通常作为OLE Package对象插入
-
需要处理不同的内容类型(MIME types)
-
注意内存使用,大附件需要流式处理
根据你的具体需求和技术栈选择合适的库。