OpenXML文档,当没有扩展名时,如何确定哪个是哪个?

4

目前我所做的,并且起作用的是这个:

private string DetermineOpenXML(string file)
    {

        try
        {
            SpreadsheetDocument doc = SpreadsheetDocument.Open(file, false);
            doc.Close();
            return ".xslx";
        }
        catch
        {
            try
            {
                WordprocessingDocument doc = WordprocessingDocument.Open(file, false);
                doc.Close();
                return ".docx";
            }
            catch
            {
                try
                {
                    PresentationDocument doc = PresentationDocument.Open(file, false);
                    doc.Close();
                    return ".pptx";
                }
                catch
                {
                    return string.Empty;
                }
            }
        }
    }

我认为除了试错之外,还应该有更好的方法来确定文件类型。我正在开发一个小程序,用于查找文件应该具有的扩展名。这是因为我从数据库中获取的文件有时没有扩展名,有时又有错误的扩展名。
我已经找到了所有OpenXML文档共享的文件签名:"50 4B 03 04 14 00 06 00",它接近于zip文件的签名,我也可以使用zip程序打开OpenXML文件并查看其内容。也许这就是我应该采取的解决方案,但我希望能更快速/更容易地使用OpenXML SDK,并且它是否有属性或其他东西可以为我检查它。
编辑: 我已经添加了一个答案,尽管它适用于我的当前目的,但我仍希望看到是否有更好的解决方案。它没有考虑到扩展名应该是模板文件。
2个回答

4

我最终使用了System.IO.Packaging。

private string anotherOpenXmlAttempt(string file)
    {
        string ext = string.Empty;
        Package package = Package.Open(file);
        if (package.PartExists(new Uri("/word/document.xml", UriKind.Relative)))
        {
            ext = ".docx";
        }
        else if (package.PartExists(new Uri("/xl/workbook.xml", UriKind.Relative)))
        {
            ext = ".xslx";
        }else if (package.PartExists(new Uri("/ppt/presentation.xml", UriKind.Relative)))
        {
            ext = ".pptx";
        }

        package.Close();
        return ext;
    }

我还没有进行过广泛的测试,但是在当前文件中已经可以使用。

如果有人有更好的解决方案,我会保持问题的开放状态。


那是一种更好的做法。 - Todd Main
是的,而且速度更快,但它不考虑是否为模板文件,在我的情况下这并不重要,因为文件现在至少会在正确的程序中打开,但对于可能遇到相同情况并需要模板的人来说,他们可能需要做更多的工作。 - Henrik Bøgelund Lavstsen
你有没有找到比这更好的方法? - Jonah
1
应该是“.xlsx”,而不是“.xslx”... - thomiel

0

从我使用OpenXMLSDK2的经验来看,它更适用于操作文档的xml内部。如果您只需要扩展类型,那么为什么不直接使用:

string extension = System.IO.Path.GetExtension(filename);

值得注意的是,try catch对于仅确定外部细节而言是一种昂贵的方法,因为它将需要所有异常细节、堆栈跟踪等等。

此外,Excel的扩展类型是.xslx而不是.xslt,后者是“可扩展样式表语言转换”。

希望这有所帮助!


这个方法只会返回文件的扩展名,使用filepath.Substring(LastIndexOf('.')),但是这并行不通,因为我所找的文件没有扩展名。 - Henrik Bøgelund Lavstsen
是的,第二个方法更好,你甚至可以尝试循环遍历包中的部分,查找字符串 "xl"、"word"、"ppt",例如 part.Uri.OriginalString.Split('/')[1] == "ppt",因为它们总是以扩展类型开头,一旦找到就可以跳出循环。 - JoeKir
听起来像是个好主意,我相信第一部分带有其中一个关键字的索引在2或3,因此循环会非常短。 - Henrik Bøgelund Lavstsen
我刚刚测试了一下,我的方法在900个文件上花费了7105275个时钟周期,而使用split则需要11151623个时钟周期,速度慢了很多,可能是因为需要进行字符串操作的缘故。 - Henrik Bøgelund Lavstsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接