检查 Excel 文件是否在 .NET Core 中受密码保护

Check whether Excel file is password protected in .NET Core

技术:

C#

ASP.NET 核心 2.0

Excel(主要是 OpenXml,但偶尔有遗留文档)

目前正在使用 ExcelDataReader 读取文件。

场景:

我需要在服务器上存储一些文件并在以后访问它们以进行工作。用户通过网络上传文件 API 并打电话请求以同样的方式完成工作。

一些用户 password-protect 他们的 Excel 文件,要求这些文件在服务器上保持 password-protect 状态。

问题:

我需要检测文档是否 password-protected 以便我可以使用适当的配置来访问它。

我用谷歌搜索了很多,但它主要是 Workbook.HasPassword(我认为这是 Excel.Interop 的一部分,我想避免添加)。我还发现 this link 关于 Office 文档的类似问题,其中的解决方案是通过文件流针对各种 header 数据的长清单。

理想情况下,我想要一个不需要我打开文件的 Core-friendly 解决方案。我不经常处理文档,所以我不知道下一步该去哪里。

有什么建议吗?

如果不打开文件,您将无法知道该文件是否受密码保护。该信息在文件中(据我所知);它没有暴露在文件系统中。

您应该能够使用 OpenXml SDK 快速掌握它。创建一个不受保护的文件。复制它。打开副本并设置密码并保存。然后使用 openXml "Productivity Tool" 来区分这两个文件("Compare Files",在工具栏上)。它应该在查找位置快速归零。

因为您已经在使用 ExcelDataReader,所以在 try-catch 子句中打开文件并处理 InvalidPasswordException:

bool ExcelFileRequiresPassword(Stream stream) {
    try {
        using (ExcelReaderFactory.CreateReader(stream)) { }
    } catch (InvalidPasswordException) {
        return true;
    }
    return false;
}

这在性能方面还算不错。在幕后,它只检查文件中的相关 headers,并处理所有血淋淋的 BIFF、ZIP 和版本控制细节。如果没有密码,则不会读取任何数据。

这是我添加的旧 post,但最近我想在不使用外部库的情况下确定电子表格是否在 C# 中受密码保护,我最终创建了以下代码。

可能有些案例和文件格式我没有找到,但我希望这能让你走上正轨。

注意:比较文本中的空格数很重要,因此在剪切和粘贴时要小心。

static bool IsExcelPasswordProtected(string strSource)
{
    bool blResult = false;

    if (File.Exists(strSource))
    {
        char[] chBuffer = new char[4096];   // The character strings usually occur within the first 2K in my testing, but just in case
        TextReader trReader = new StreamReader(strSource, Encoding.UTF8, true);

        // Read the buffer
        trReader.ReadBlock(chBuffer, 0, chBuffer.Length);
        trReader.Close();

        // Remove non-printable and unicode characters, we're only interested in ASCII character set
        for (int i = 0; i < chBuffer.Length; i++)
        {
            if ((chBuffer[i] < ' ') || (chBuffer[i] > '~')) chBuffer[i] = ' ';
        }

        string strBuffer = new string(chBuffer);

        // .xls format files, version 97 to 2003 contains this text when password protected
        if (strBuffer.Contains("M i c r o s o f t   E n h a n c e d   C r y p t o g r a p h i c   P r o v i d e r"))
        {
            blResult = true;
        }
        // .xlsx format files contain this text when password protected
        else if (strBuffer.Contains("E n c r y p t e d P a c k a g e"))
        {
            blResult = true;
        }
        // .xlsx format files contain this text when not password protected
        else if (strBuffer.Contains("[Content_Types]"))
        {
            blResult = false;
        }
        // .xlsx format files contain this text when not password protected
        else
        {
            blResult = false;
        }
    }
    else
    {
        // File not found...deal with as you wish
    }

    return (blResult);
}