如何实现PDF网页免密展示、下载后需密码打开(iTextSharp)
解决方案
要实现网页预览PDF无需密码、下载后需验证密码的需求,核心思路是分场景输出不同版本的PDF:在线预览时输出解密后的无密码PDF,下载时直接输出加密后的带密码PDF。具体实现步骤如下:
1. 先生成加密后的PDF(保留用户/所有者密码)
首先按需求生成带用户密码和所有者密码的加密PDF,保存为字节数组用于后续处理:
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); byte[] userpwd = encoding.GetBytes("Secretinfo"); byte[] ownerpwd = encoding.GetBytes("SecretinfoAdmin"); byte[] encryptedPdfBytes; // 生成加密PDF到内存流 using (iTextSharp.text.Document pdfDoc = new iTextSharp.text.Document()) using (System.IO.MemoryStream encryptedMs = new System.IO.MemoryStream()) using (iTextSharp.text.pdf.PdfCopy pdfCopy = new iTextSharp.text.pdf.PdfCopy(pdfDoc, encryptedMs)) { // 设置加密规则:用户密码、所有者密码、权限、加密强度 pdfCopy.SetEncryption( userpwd, ownerpwd, iTextSharp.text.pdf.PdfWriter.HideWindowUI | iTextSharp.text.pdf.PdfWriter.HideToolbar | iTextSharp.text.pdf.PdfWriter.HideMenubar | iTextSharp.text.pdf.PdfWriter.ALLOW_PRINTING, iTextSharp.text.pdf.PdfWriter.STANDARD_ENCRYPTION_128 ); using (iTextSharp.text.pdf.PdfReader pdfReader = new iTextSharp.text.pdf.PdfReader(ra, null)) { pdfDoc.Open(); for (int i = 1; i <= pdfReader.NumberOfPages; i++) { pdfCopy.AddPage(pdfCopy.GetImportedPage(pdfReader, i)); } } pdfDoc.Close(); encryptedPdfBytes = encryptedMs.ToArray(); }
2. 分场景处理输出
场景A:网页在线预览(无需密码)
用用户密码解密加密PDF,生成无密码的版本输出给浏览器,这样浏览器的PDF阅读器可以直接加载展示:
Response.Clear(); Response.ClearContent(); Response.ClearHeaders(); Response.ContentType = "application/pdf"; using (iTextSharp.text.pdf.PdfReader decryptedReader = new iTextSharp.text.pdf.PdfReader(encryptedPdfBytes, userpwd)) using (System.IO.MemoryStream decryptedMs = new System.IO.MemoryStream()) using (iTextSharp.text.pdf.PdfStamper stamper = new iTextSharp.text.pdf.PdfStamper(decryptedReader, decryptedMs)) { // 移除加密,生成无密码的PDF stamper.SetEncryption(null, null, decryptedReader.GetPermissions(), iTextSharp.text.pdf.PdfWriter.STANDARD_ENCRYPTION_128); stamper.Close(); Response.AddHeader("content-length", decryptedMs.Length.ToString()); Response.BinaryWrite(decryptedMs.ToArray()); } Response.Flush(); Response.End();
场景B:PDF下载(需密码验证)
直接输出之前生成的加密PDF字节数组,用户下载后打开时会被要求输入密码:
Response.Clear(); Response.ClearContent(); Response.ClearHeaders(); Response.ContentType = "application/pdf"; // 添加下载头,指定文件名 Response.AddHeader("Content-Disposition", "attachment; filename=protected_document.pdf"); Response.AddHeader("content-length", encryptedPdfBytes.Length.ToString()); Response.BinaryWrite(encryptedPdfBytes); Response.Flush(); Response.End();
关键原理说明
- PDF的用户密码用于解密文档内容,在线预览时我们提前用用户密码解密,生成无密码的PDF流给浏览器,避免浏览器弹出密码输入框。
- 下载时直接提供加密后的PDF文件,用户本地打开时必须输入正确的用户/所有者密码才能访问内容,同时所有者密码可用于修改文档权限。
内容的提问来源于stack exchange,提问作者Artemis
相关产品推荐
相关产品推荐

