2013-07-16 285 views
11

我正在制作一个应用程序,该应用程序应该显示带有密码的PDF。这是我的代码:用iTextSharp打开受密码保护的pdf文件

protected void Page_Load(object sender, EventArgs e) 
{ 
    if (!Page.IsPostBack) 
    { 
     try 
     { 
      string filePath = Request.QueryString["filePath"]; 
      if (filePath.ToUpper().EndsWith("PDF")) 
      { 
       copyPDF(filePath); 
      } 
     } 
     catch 
     { 
      string message = "<script language='Javascript'>alert('File Not Found! Call Records Department for verification. ')</script>"; 
      ScriptManager.RegisterStartupScript(Page, this.GetType(), message, message, false); 
     } 
    } 
} 
public void copyPDF(string filePath) 
{ 
    iTextSharp.text.pdf.RandomAccessFileOrArray ra = new iTextSharp.text.pdf.RandomAccessFileOrArray(Server.MapPath(ResolveUrl(filePath))); 
    if (ra != null) 
    { 
     System.IO.MemoryStream ms = new System.IO.MemoryStream(); 
     byte[] password = System.Text.ASCIIEncoding.ASCII.GetBytes("Secretinfo"); 
     iTextSharp.text.pdf.PdfReader thepdfReader = new iTextSharp.text.pdf.PdfReader(ra, password); 
     int pages = thepdfReader.NumberOfPages; 
     iTextSharp.text.Document pdfDoc = new iTextSharp.text.Document(); 
     iTextSharp.text.pdf.PdfCopy pdfCopy = new iTextSharp.text.pdf.PdfCopy(pdfDoc, ms); 

     pdfDoc.Open(); 
     int i = 0; 
     while (i < pages) 
     { 
      pdfCopy.AddPage(pdfCopy.GetImportedPage(thepdfReader, i + 1)); 
      i += 1; 
     } 
     pdfDoc.Close(); 
     Byte[] byteInfo = ms.ToArray(); 
     Response.Clear(); 
     Response.ContentType = "application/pdf"; 
     Response.AddHeader("content-length", byteInfo.Length.ToString()); 
     Response.BinaryWrite(byteInfo); 
     Response.Flush(); 
     Response.End(); 
    } 
} 

我的代码有没有问题打开PDF文件,没有密码,但它不能与密码打开的PDF,即使密码被提供。应用程序会执行catch。我的代码似乎有什么问题?

编辑: 我删除了抓住看到抛出的异常。

异常详细信息信息:System.ArgumentException:PdfReader不是所有者密码打开

报告说,错误的来源是51

Line 49: while (i < pages) 
Line 50: { 
Line 51:   pdfCopy.AddPage(pdfCopy.GetImportedPage(thepdfReader, i + 1)); 
Line 52:   i += 1; 
Line 53: } 
+0

哪个异常被抛出? – mkl

+0

它不会抛出异常。它执行catch语句,在这种情况下是一个弹出窗口,说'文件未找到!呼叫记录部门进行验证。' – Artemis

+0

嘿@mkl我删除了Catch,以找出抛出什么样的异常它说** System.ArgumentException:PdfReader未打开所有者密码**。 – Artemis

回答

17

行有关加密某些操作文件iText(Sharp)要求文件不仅仅是用用户密码打开,而是用所有者密码打开。这相当于在PDF规范这些密码的定义:是否需要额外的操作应在解密文件被允许取决于

其密码(如果有的话)文件打开时供给和任何访问限制是创建文档时指定:

  • 打开文档与正确的所有者密码应该让全(所有者)访问该文件。这种无限制访问包括更改文档密码和访问权限的能力。
  • 使用正确的用户打开文档(或使用默认密码打开文档)应允许根据文档的加密字典中指定的用户访问权限执行其他操作。

(在ISO 32000-1节7.6.3.1)

的iText(夏普)目前没有详细检查文档的加密字典指定的用户访问权限,而是总是需要业主需要某些权限的操作的密码,以及从文档中复制整个页面的权限都是其中之一。

这已经说了,在iText的(夏普)的开发人员非常了解(因为问了很多这样的问题)

  • 是iText的(夏普)的用户可能有权即使没有所有者密码来执行这样的操作由于之前提到的用户访问权限在文档的加密词典中指定,
  • 有各种各样的PDF,其各个所有者向其应用所有者密码(以防止他人滥用),然后将其忘记(或通过使用一个随机生成的人从来不知道它开始)和
  • iText(Sharp)(开源)很容易被任何人修补,不会尊重用户和所有者密码之间的差异。

要允许用户做他们有权什么,防止库的补丁的副本的蔓延,iText的(夏普)包含了PdfReader类此测试的覆盖:

/** 
* The iText developers are not responsible if you decide to change the 
* value of this static parameter. 
* @since 5.0.2 
*/ 
public static bool unethicalreading = false; 

因此,通过设置

PdfReader.unethicalreading = true; 

您全局覆盖此权限检查机制。

请尊重PDF作者的权利,如果您确实有权执行相关操作,请仅使用此覆盖。

+0

我用这个,现在我得到一个** InvalidCastException **错误_无法投射“iTextSharp.text.pdf.PdfArray”类型的对象来键入'iTextSharp.text.pdf.PRIndirectReference'._ – Artemis

+0

然后,无论您的PDF或者itext有错误。你能提供PDF分析吗? – mkl

+0

如何为您提供PDF? (对不起,如果你告诉我怎么做,我会非常乐意。) – Artemis

0

我应用这个解决方法,它的工作原理:

private void fixIssue(PdfReader pdfReader) throws Exception { 
     Field f = pdfReader.getClass().getDeclaredField("ownerPasswordUsed"); 
     f.setAccessible(true); 
     f.setBoolean(pdfReader, true); 

} 
+0

虽然我知道有些场合必须使用在iText中反射有趣的效果,这里没有必要这样做。 – mkl

+0

嗯,这只是一个解决方法,正如我写的。但它有效:)可能使用提供的构造函数之一来设置ownerPasswordUsed为true更有意义。http://sourceforge.net/p/itext/code/HEAD/tree/trunk/itext/src/main/java/com/itextpdf/text/pdf/PdfReader.java –