检查 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);
}
技术:
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);
}