我有一个第三方库,该库创建xlsx文件。它不使用OpenXmlSDK,它结合了xml标记片段中的文件。对于压缩,使用了ZipArchive类。 但是当我尝试使用OpenXmlSDK
var document = SpreadsheetDocument.Open(fileStream, false);
它失败并出现错误:
DocumentFormat.OpenXml.Packaging.OpenXmlPackageException:'指定的程序包无效。主要部分丢失了。'
MS Excel正常打开此文件。从Excel重新保存会有所帮助。
我也解压缩文件,然后再次压缩它们(不做任何更改),尝试再次调用上面的代码,它可以工作。
问题出在哪里?如何压缩可用于OpenXmlSDK的xlsx文件?
解决方案
问题在于第三方库保存文件。包含在zip中的文件的条目名称带有\
而不是/
。编辑该库的代码以解决此问题,一切正常。
答案 0 :(得分:1)
经过研究,我发现人们在以下两种情况下抱怨这种异常:
由于您是从流中打开文件的,因此第二种原因在这种情况下不适用。
如果不是字体使用的原因,请尝试在Open XML Productivity Tool(https://www.microsoft.com/en-us/download/details.aspx?id=30425)中使用Excel保存之前和之后手动比较文件版本。
如果文档内容没有差异,请尝试比较存档压缩设置。
更新
似乎我找到了有关此问题的更多信息,可以帮助找到解决方案。
我能够通过创建带有ZipFile.CreateFromDirectory(@"C:\DirToCompress", destFilePath, CompressionLevel.Fastest, false);
的存档来复制主要部分丢失。错误。
然后,我检查了使用Package.Open(destFilePath, FileMode.Open, FileAccess.Read)
打开文件时实际上列出了文件中找到的 0 个部分。
在验证了一些差异之后,我注意到在正确的xlsx文件中,嵌套在归档文件的文件夹中的条目具有FullName
路径,这些路径使用/
字符表示,例如:_rels/.rels
。在损坏的文件中,名称用\
字符书写,例如:_rels\.rels
。
您可以通过使用ZipArchive
类(例如:new ZipArchive(archiveStream, ZipArchiveMode.Read, false, UTF8Encoding.UTF8);
)打开文件并检查Entries
集合来调查它。
要注意的重要一点是,Office Open XML规范中描述的部件有命名规则:https://www.ecma-international.org/news/TC45_current_work/Office%20Open%20XML%20Part%202%20-%20Open%20Packaging%20Conventions.pdf
作为测试,我编写了一个代码,该代码使用ZipArchive
类打开损坏的xlsx文件,并通过复制其内容并将\
替换为/
来重写每个条目。重新创建的条目。执行此操作后,似乎可以通过SpreadsheetDocument.Open(...)
方法正确打开生成的文件。
请注意,我使用的名称固定方法非常简单,在某些情况下可能不够用或无法正常工作。但是,这些说明可能有助于找到所需的解决方案。