如何在将文件上传到服务器之前检测Word文档是否受密码保护?

时间:2013-01-15 21:45:36

标签: c# .net webforms

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

在上传文件之前,有没有办法确定Microsoft Office文件(Word,Powerpoint和Excel)是否受密码保护? 根据{{​​3}},我已实现以下内容,但在尝试打开受密码保护的文件时,会抛出错误“文件包含损坏的数据”。

 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;
     }
 }

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

5 个答案:

答案 0 :(得分:2)

尝试使用此代码:

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;
}

答案 1 :(得分:0)

以下是.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)
    {
        String noPW = "C:\\Users\\David\\Desktop\\Doc1.docx";
        String pwProtected = "C:\\Users\\David\\Desktop\\Test.docx"; 
    //         if (isProtected(pwProtected))
    //             outcome.Text = ("Document Is Password Protected");
    //         else
    //             outcome.Text = ("Document Is NOT Password Protected");

        if (isProtected(noPW))
            outcome.Text = ("Document Is Password Protected");
        else
            outcome.Text = ("Document Is NOT Password Protected");
    }

以下是文件后面的.aspx.cs代码


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using Microsoft.Office.Interop.Word;
    using System.Runtime.InteropServices;
    using Microsoft.Office.Interop.Word;


    namespace TestApp
    {
        public partial class TestForm : System.Web.UI.Page
        {

            protected void Page_Load(object sender, EventArgs e)
            {

            }
            public static bool isProtected(object filePath)
            {
                Application myapp = new Application();

                object pw = "thispassword";
                try
                {

                    // Trying this for Word document
                    myapp.Documents.Open(ref filePath, PasswordDocument: ref pw); // try open
                    myapp.Documents[ref filePath].Close();  // close it if it does open    
                }
                catch (COMException ex)
                {
                    if (ex.HResult == -2146822880) // Can't Open Doc Caused By Invalid Password
                        return true;
                    else
                        Console.WriteLine(ex.Message + "  " + ex.HResult);  // For debugging, have only tested this one document.
                }
                return false;
            }
        }

    }

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

答案 2 :(得分:0)

回答这个问题:

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

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

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

答案 3 :(得分:0)

notme一样,我不知道一种方法可以判断一个文件是否受密码保护之前甚至可以上传部分文件,但是这个问题的接受答案是技术上的很棒,有点矫枉过正。

有关更简单,更快速的方法来测试文件是否受密码保护,请参阅Detect password protected word file

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

答案 4 :(得分:0)

对不起,我在这里参加聚会有点晚了。由于我还没有50的声誉,所以我无法评论Tomasso Belluzo的答案,但是当我实现它时,我发现了以下几点:

  1. 要获取前缀,请使用Encoding.UTF7.GetString
  2. 要检查“ EncryptedPackage”,我使用了Encoding.Unicode.GetString,它消除了删除所有\ 0的需要