因為客戶要求配合將itextsharp 降版,因此碰到舊版itextsharp 對受保護PDF 的處理方法與新版的稍有不同。順便紀錄itextsharp 要如何處理加密或受保護的PDF
系統環境:
Windows 11、Visual Studio 2022、iTextSharp-LGPL 4.1.6、iTextSharp 5.5.13.3
加密種類
PDF的加密分兩種
User Password:PDF密碼。開啟PDF 時需要輸入密碼。
Owner Password:受保護的PDF。可以直接開啟PDF,但是無法編輯內容。開啟檔案時,PDF reader 顯示檔名的後面會顯示 (已保護)。
處理User Password
這邊的處理不是指破解密碼,是指程式要對輸入密碼正確及錯誤的狀況處理
string password = "12345678";
byte[] bytes = File.ReadAllBytes("有密碼的PDF 檔案路徑");
PdfReader reader;
try
{
reader = new PdfReader(bytes, Encoding.UTF8.GetBytes(password));
// 密碼正確可以往下操作
reader = new PdfReader(bytes);
// 如果沒帶密碼開啟有密碼的PDF,會直接跳到BadPasswordException
}
catch (BadPasswordException)
{
// 密碼錯誤也會跑到BadPasswordException
Console.WriteLine("密碼錯誤");
}
研究了一陣子,發現要檢查PDF 有沒有密碼只能用try-catch 方式,覺得也蠻奇怪的……
處理Owner Password
當要合併、修改 受保護的PDF,兩個版本要用不同的做法。
PdfReader reader = new PdfReader(bytes);
// iTextSharp 5.5.13.3
PdfReader.unethicalreading = true;
// iTextSharp-LGPL 4.1.6
if (reader.IsEncrypted())
{
try
{
// 直接修改PdfReader.encrypted 成false
var field = reader.GetType().GetField("encrypted", BindingFlags.NonPublic | BindingFlags.Instance);
field?.SetValue(reader, false);
}
catch { }
}
using (MemoryStream stream = new MemoryStream())
{
try
{
// PdfStamper 是修改PDF 用的物件
PdfStamper stamper = new PdfStamper(reader, stream);
}
catch
{
// 如果沒有經過上面的步驟解開保護,就會拋出例外狀況
}
}