是否有方法通过OpenXML库读取加密的xlsx文件?
关于通过OpenXML读取加密XLSX文件的实现方案
原生OpenXML SDK不支持直接读取文件级加密的XLSX文件:加密后的XLSX已经不是标准ZIP压缩的OOXML结构,而是遵循微软Office加密文档规范封装的OLE复合文档,直接用SDK打开会触发文件格式损坏的报错。所有可行实现的前提是你持有该文件的合法打开密码,无密码场景不存在稳定可用的合法读取路径。
方案1:Windows环境高兼容实现(依赖本地Excel)
这个方案和微软Office的加密逻辑完全兼容,不会出现解密后格式错乱的问题,适合桌面端场景:
- 运行环境需要安装2007及以上版本的Excel,项目添加对
Microsoft.Office.Interop.Excel的互操作引用 - 先通过Excel互操作组件传入密码打开加密文件,另存为无加密的临时文件
- 关闭互操作相关对象、释放进程后,即可用OpenXML SDK正常读取临时文件内容,读取完成后删除临时文件即可
- 核心代码参考:
using Excel = Microsoft.Office.Interop.Excel; using System.Runtime.InteropServices; using DocumentFormat.OpenXml.Packaging; // 初始化Excel实例 var excelInstance = new Excel.Application(); excelInstance.DisplayAlerts = false; // 传入密码打开加密文件 var targetWorkbook = excelInstance.Workbooks.Open( Filename: "你的加密xlsx文件路径", Password: "文件对应的打开密码" ); // 生成无加密临时文件 var tempFilePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N") + ".xlsx"); targetWorkbook.SaveAs(Filename: tempFilePath, Password: string.Empty); // 关闭工作簿、退出Excel实例,释放COM对象避免残留进程 targetWorkbook.Close(); excelInstance.Quit(); Marshal.ReleaseComObject(targetWorkbook); Marshal.ReleaseComObject(excelInstance); // 用OpenXML读取临时文件 using (var spreadDoc = SpreadsheetDocument.Open(tempFilePath, isEditable: false)) { // 编写你的正常OpenXML读取逻辑即可 } // 清理临时文件 File.Delete(tempFilePath);
这个方案的缺点是必须依赖Windows系统和本地安装的Excel,不适合服务端部署、跨平台部署场景。
方案2:跨平台无依赖实现
如果需要在Linux/macOS环境运行,或是不想在服务器上安装Office,可以采用纯代码解密的方案:
- 按照Office加密文档规范解析加密文件的头信息,通过密码派生解密密钥,解密出原始的标准OOXML格式流,不需要落地临时文件
- 将解密得到的内存流直接传入
SpreadsheetDocument.Open的流参数重载,即可正常用SDK读取内容 - 实现时需要注意同时兼容Office的标准加密和敏捷加密两种模式,否则会出现高版本Excel保存的加密文件解密失败的问题。.NET生态已有成熟的开源实现可完成该解密流程,不需要从零编写加解密逻辑。
避坑提示:不要尝试直接修改加密文件后缀名、用ZIP类库强行解压读取,加密后的文件已经不是ZIP格式,这类操作必然报错;OpenXML SDK自带的权限相关API仅能处理文件内部的权限管控,无法处理文件级的打开加密。
内容的提问来源于stack exchange,提问作者Ruslan Slim
相关产品推荐
相关产品推荐

