【问题标题】:How to detect if a Word document is password protected before uploading the file to server?如何在将文件上传到服务器之前检测 Word 文档是否受密码保护?
【发布时间】:2013-01-15 21:45:35
【问题描述】:

我正在开发一个允许用户上传不同文件格式的网站。我们需要限制用户上传受密码保护的文件。

有没有办法在上传文件之前确定 Microsoft Office 文件(Word、Powerpoint 和 Excel)是否受密码保护? 根据http://social.msdn.microsoft.com/Forums/en/oxmlsdk/thread/34701a34-f1d4-4802-9ce4-133f15039c69,我已经实现了以下内容,但是在尝试打开受密码保护的文件时,它会抛出一个错误,提示“文件包含损坏的数据”。

 using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, false))
 {
     DocumentProtection dp =
         wordDoc.MainDocumentPart.DocumentSettingsPart.Settings.GetFirstChild<DocumentProtection>();
     if (dp != null && dp.Enforcement == DocumentFormat.OpenXml.OnOffValue.FromBoolean(true))
     {
         return true;
     }
 }

还有其他方法可以确定吗?

【问题讨论】:

  • 如果您处于代码的这一点,则该文件已经上传。你只是还没有对它做任何事情。
  • 正在上传可能已损坏或格式错误的文档。
  • 我认为文档没有损坏,可以在MS Office中成功打开。
  • 请务必告诉我们您正在使用哪种类型的文档以及哪些版本:例如,任何 Excel 2003 文档?

标签: c# .net webforms


【解决方案1】:

试试这个代码:

public static Boolean IsProtected(String file)
{
    Byte[] bytes = File.ReadAllBytes(file);

    String prefix = Encoding.Default.GetString(bytes.Take(2).ToArray());

    // Zip and not password protected.
    if (prefix == "PK")
        return false;

    // Office format.
    if (prefix == "ÐÏ")
    {
        // XLS 2003
        if (bytes.Skip(0x208).Take(1).ToArray()[0] == 0xFE)
            return true;

        // XLS 2005
        if (bytes.Skip(0x214).Take(1).ToArray()[0] == 0x2F)
            return true;

        // DOC 2005
        if (bytes.Skip(0x20B).Take(1).ToArray()[0] == 0x13)
            return true;

        // Guessing
        if (bytes.Length < 2000)
            return false;

        // DOC/XLS 2007+
        String start = Encoding.Default.GetString(bytes.Take(2000).ToArray()).Replace("\0", " ");

        if (start.Contains("E n c r y p t e d P a c k a g e"))
            return true;

        return false;
    }

    // Unknown format.
    return false;
}

【讨论】:

  • 在调用上述方法之前我不需要上传文件吗?因为它使用文件路径
  • 我认为第一个是一样的,不是吗? WordprocessingDocument.Open() 需要路径或流...
  • 是的..它确实需要一个流。
  • 试过上面的代码..不起作用..为密码保护文件返回false。
  • 这个文件的版本是多少?
【解决方案2】:

抱歉,我在这里参加聚会有点晚了。由于我还没有 50 名声望,我无法评论 Tomasso Belluzo 的答案,但在我实施它时,我发现了以下内容:

  1. 要获取前缀,我使用 Encoding.UTF7.GetString
  2. 要检查“EncryptedPackage”,我使用 Encoding.Unicode.GetString,这样就无需删除所有 \0s

【讨论】:

    【解决方案3】:

    回答问题:

    为了判断文件是否受密码保护,您需要在浏览器中打开该文件并对其进行处理。目前,打开文件客户端的唯一机制是通过 HTML5 的 FileAPI,这不是普遍支持的。这意味着没有可靠的方法可以做到这一点。

    现在,您可以在服务器上测试文件,以确定它是否受密码保护,然后根据您的规则将其丢弃或保存。

    顺便提一下,您提供的代码是服务器端代码。只需对其进行修改以捕获损坏的异常并向用户显示有关文件如何损坏或密码保护的消息,并附上有关您如何不允许上传受密码保护的文件的注释。

    【讨论】:

      【解决方案4】:

      .aspx 源文件中包含以下内容

       Page Language="C#" AutoEventWireup="true" CodeBehind="TestForm.aspx.cs" Inherits="TestApp.TestForm"
      
       !DOCTYPE html PUBLIC
       Reference Page ="~/TestForm.aspx" // Note: Removed all HTML tags
      
      protected void Upload_Click(object sender, EventArgs e) { 字符串 noPW = "C:\\Users\\David\\Desktop\\Doc1.docx"; String pwProtected = "C:\\Users\\David\\Desktop\\Test.docx"; // if (isProtected(pwProtected)) // 结果.Text = ("文档受密码保护"); // 别的 // 结果.Text = ("文档不受密码保护"); if (isProtected(noPW)) 结果.Text = ("文档受密码保护"); 别的 结果.Text = ("文档不受密码保护"); }

      .aspx.cs 代码隐藏文件中包含以下内容

      使用系统; 使用 System.Collections.Generic; 使用 System.Linq; 使用 System.Web; 使用 System.Web.UI; 使用 System.Web.UI.WebControls; 使用 Microsoft.Office.Interop.Word; 使用 System.Runtime.InteropServices; 使用 Microsoft.Office.Interop.Word; 命名空间 TestApp { 公共部分类 TestForm : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } 公共静态布尔 isProtected(对象文件路径) { 应用程序 myapp = new Application(); 对象 pw = "这个密码"; 尝试 { // 对 Word 文档试试这个 myapp.Documents.Open(ref filePath, PasswordDocument: ref pw); // 尝试打开 myapp.Documents[参考文件路径].Close(); // 如果打开就关闭 } 捕捉(COMException ex) { if (ex.HResult == -2146822880) // 因密码无效而无法打开文档 返回真; 别的 Console.WriteLine(ex.Message + " " + ex.HResult); // 调试用,只测试过这一份文件。 } 返回假; } } }

      至少在我的计算机上,我得到了两个文件的预期输出,但这并不是你所说的代码详尽测试。此外,我尝试使用 FileUpload 控件上传文件,但我收到 COM 错误“找不到 C:\Windows\System\fileName.docx”,这让我很困惑,因为上传的文件来自我的桌面,但是你可能知道为什么会发生这种情况,因为您比我更熟悉 ASP.NET。不管怎样,这段代码只是尝试一下,希望对您有所帮助。

      【讨论】:

      • 密码保护的文件被认为是加密的,不过,我不知道它们是否扩展到 Word 文档,但它们在打开时确实需要密码... MSDN 的定义“加密文件,以便只有帐户用来加密的文件可以解密。”
      • 是的,但是你有理由相信这些文件会导致FileAttributes.Encrypted 被设置吗?
      • 我不确定是否完全诚实,我会在一秒钟内测试一下,如果我在之前的评论中表现得很粗鲁,对不起,我的女朋友打电话来唠叨时正在写它我有事,大声笑。
      • 原代码不起作用,我尝试了几件事后更新了答案。
      • 我无法在 asp.net Web 应用程序中编译上述代码。那是 Windows 应用程序类吗?
      【解决方案5】:

      就像notme 我不知道如何判断文件是否在上传文件的一部分之前之前受密码保护,但是这个问题的公认答案虽然在技术上很棒,有点矫枉过正。

      请参阅Detect password protected word file,了解一种更简单、更快捷的方法来测试文件是否受密码保护。

      另外,对于那些在VBA/S中寻找解决方案的人来说,以下是前者的版本,它很容易适应后者。 www.ozgrid.com/forum/showthread.php?t=148962。虽然我建议检查 err.number = 5408(受保护时会使用错误的密码抛出什么),而不是使用任何 err.number 来确定该文件是否受密码保护。

      【讨论】:

      • 不知道为什么文件头分析对你来说太过分了,对我来说,在服务器的 后端 上引入 VBA 或 NetOffice 只是为了知道文件受到保护是一种有保证的方法将来射双腿。甚至您提到的帖子中的那个人也使用 NetOffice 警报为受保护文件打开了这种拍摄方式。 Tomasso 的答案的强大之处在于它甚至可以移植到客户端 JS,因此在上传之前将知道事实文件的受保护。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-24
      • 1970-01-01
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 2015-08-24
      相关资源
      最近更新 更多