如何在 Java 中使用 GroupDocs.Signature 建立 PDF 數位簽章
簡介
是否曾經將重要合約透過電郵寄出,卻要等上好幾天才有人列印、簽署、掃描再回傳?是啊,我們都曾有過這種經驗。在當今節奏快速的數位世界,這種延遲不僅不方便,更是生產力的殺手。
在 Java 中建立 PDF 數位簽章 能優雅地解決此問題。數位簽章在大多數司法管轄區具備法律效力,比手寫簽名更安全,且可在數秒內完成,而非數天。對於開發合約入口網站、發票審批流程或任何處理機密文件的 Java 開發者而言,了解如何在 Java 中建立 PDF 數位簽章是必備技能,而非可有可無。
在本教學中,你將學會如何使用 GroupDocs.Signature for Java,這是目前最簡易的 Java PDF 簽章函式庫之一,將數位簽章加入 PDF 文件。無論你是自動化合約工作流程、保護員工紀錄,或是建置多方簽署平台,本指南都能滿足你的需求。
你將學到的內容
- 如何載入與準備 PDF 文件以進行數位簽署
- 使用憑證與自訂外觀設定數位簽章選項
- 實作完整的簽署工作流程並妥善處理錯誤
- 憑證管理的安全最佳實踐
- 何時應在 Java 生態系統中選擇 GroupDocs.Signature 而非其他函式庫
- 疑難排解實際會遇到的常見問題
讓我們改變你在 Java 應用程式中處理文件簽署的方式。
快速問答
- 簽署的主要類別是什麼?
Signature為所有簽署操作的入口點。 - 我需要付費授權嗎? 免費試用可用於開發;商業使用則需購買正式授權。
- 我可以簽署非 PDF 文件嗎? 可以——支援 Word、Excel、圖片等多種格式,使用相同的 API。
- GroupDocs.Signature 支援多少種格式? 超過 30 種輸入與輸出格式,包含 PDF、DOCX、XLSX、PNG、JPG 等。
- 需要哪個 Java 版本? JDK 8 或以上;此函式庫相容於 Java 11、17 及更新版本。
什麼是建立 PDF 數位簽章?
PDF 數位簽章 是嵌入於 PDF 中的加密印章,用以證明簽署者身分並保證文件自簽署以來未被更改。此技術可實現具法律效力的電子合約,同時讓簽署流程快速且無紙化。
如何在 Java 中建立 PDF 數位簽章?
使用 Signature 類別載入 PDF,透過你的 PFX 憑證設定 DigitalSignOptions 物件,指定可選的外觀參數,然後呼叫 sign() 產生新的已簽署 PDF。整個操作通常只需三行程式碼,對於一般大小的文件執行時間不到一秒。
為何選擇 GroupDocs.Signature for Java?
GroupDocs.Signature 為需要快速、可靠方式在多種文件類型上加入數位簽章且不需深厚 PDF 專業知識的開發者而設計。它即插即用支援超過 30 種格式,內建視覺印章處理,且具商業級效能,較之低階函式庫更適合企業應用。
- 格式支援:GroupDocs.Signature 支援 30+ 種文件格式(PDF、DOCX、XLSX、PPTX、PNG、JPG、BMP、GIF 等)。
- 效能:在一般 2.8 GHz CPU 上簽署 5 頁 PDF(≈1 MB)平均 350 ms,而 iText 常需額外設定才能達到相似速度。
- API 簡潔度:所有簽署操作皆透過單一
Signature物件完成,較低階函式庫可減少高達 60 % 的樣板程式碼。
若 你需要多格式支援、簡易 API 與商業級可靠性,請選擇 GroupDocs.Signature。
考慮使用 Apache PDFBox 當你受限於開源堆疊且僅需基本的 PDF 操作時。
考慮使用 iText 若你需要超越簽署的進階 PDF 建立功能。
先決條件
必要函式庫
- GroupDocs.Signature for Java – 版本 23.12(穩定且經過充分測試)
- Java Development Kit (JDK) – 版本 8 或以上
環境設定
- 如 IntelliJ IDEA、Eclipse 或 VS Code(附帶 Java 擴充功能)等 IDE
- Maven 或 Gradle 用於相依管理(以下範例)
- 有效的 PFX/PKCS#12 格式數位憑證
憑證說明
若尚未擁有憑證,可使用 keytool 工具產生自簽憑證。請記住,自簽憑證僅適用於測試,於正式環境中不會被信任。
設定 GroupDocs.Signature for Java
將函式庫加入專案相當簡單,請選擇你的建置工具:
Maven
<dependency>
<groupId>com.groupdocs</groupId>
<artifactId>groupdocs-signature</artifactId>
<version>23.12</version>
</dependency>
Gradle
implementation 'com.groupdocs:groupdocs-signature:23.12'
若直接下載(未使用建置工具),請前往 GroupDocs.Signature for Java 版本下載。
授權取得
GroupDocs.Signature 為商業授權,但提供彈性選項:
- 免費試用 – 適合概念驗證專案;不需信用卡。
- 臨時授權 – 30 天開發授權,可延長測試。
- 購買 – 正式環境使用需購買授權;價格依部署類型而異。
加入相依後,可使用以下簡易初始化驗證設定是否正確:
import com.groupdocs.signature.Signature;
public class InitializeSignature {
public static void main(String[] args) {
Signature signature = new Signature("YOUR_DOCUMENT_DIRECTORY/sample.pdf");
// Now you're ready to use GroupDocs.Signature for Java!
System.out.println("GroupDocs.Signature initialized successfully!");
}
}
小技巧:將 "YOUR_DOCUMENT_DIRECTORY/sample.pdf" 替換為實際的 PDF 路徑。若未拋出例外,即表示已可進行簽署。
實作指南
讓我們一步步建構簽署工作流程。每個章節聚焦於特定功能,說明不僅 如何 實作,亦說明 為何 需要這樣做。
步驟 1:載入 PDF 文件
在簽署之前,需要先將 PDF 載入記憶體。可類比為編輯前先開啟 Word 文件。
Initialize and Load Document
import com.groupdocs.signature.Signature;
public class LoadDocumentFeature {
public static void main(String[] args) throws Exception {
String filePath = "YOUR_DOCUMENT_DIRECTORY/sample.pdf";
Signature signature = new Signature(filePath);
// The document is now loaded and ready for signing.
}
}
定義說明 – Signature 類別是主要的 API 入口點,代表已準備好進行簽署操作的文件。
函式庫會自動偵測檔案格式,因此相同程式碼亦可用於 Word、Excel 與圖片檔案。
常見陷阱:若 PDF 受密碼保護,請在建構子中提供密碼:
Signature signature = new Signature(filePath, new LoadOptions("yourPassword"));
步驟 2:設定數位簽章選項
在此你定義簽章的外觀與位置。數位簽章可以是隱形(僅加密資料)或以自訂印章顯示。
Configure Signature Appearance
import com.groupdocs.signature.options.sign.DigitalSignOptions;
public class SetupDigitalSignOptionsFeature {
public static void main(String[] args) {
String certificatePath = "YOUR_DOCUMENT_DIRECTORY/certificate.pfx";
String imagePath = "YOUR_DOCUMENT_DIRECTORY/image.png";
DigitalSignOptions options = new DigitalSignOptions(certificatePath);
options.setImageFilePath(imagePath);
// Set signature location and other properties
options.setLeft(100);
options.setTop(100);
options.setPageNumber(1);
options.setPassword("1234567890");
}
}
定義說明 – DigitalSignOptions 包含建立數位簽章所需的所有設定,包括憑證路徑、視覺外觀與放置座標。
- certificatePath – 包含私鑰的 PFX 檔案路徑(請妥善保管!)
- imagePath – 可選的視覺印章(例如公司標誌)。
- setLeft / setTop – 從左上角算起的 X、Y 座標(單位為像素)。
- setPageNumber – 目標頁碼(1 為首頁)。
- setPassword – 解鎖 PFX 檔案的密碼。
何時使用可見簽章:在合約需讓相關方看到簽署者姓名或標誌時使用可見簽章;對於內部流程,隱形簽章可保持文件整潔,同時提供加密驗證。
座標小技巧:可先設定 left=50, top=50,再依需求調整。亦可使用 setHorizontalAlignment() 與 setVerticalAlignment() 進行相對定位(例如右下角)。
步驟 3:簽署文件
現在就是關鍵時刻——套用數位簽章。
Complete Signing Process
import com.groupdocs.signature.Signature;
import com.groupdocs.signature.domain.SignResult;
import java.io.File;
import java.nio.file.Paths;
public class SignDocumentWithDigitalFeature {
public static void main(String[] args) throws Exception {
String filePath = "YOUR_DOCUMENT_DIRECTORY/sample.pdf";
String outputFilePath = new File("YOUR_OUTPUT_DIRECTORY",
"SignWithDigital/" + Paths.get(filePath).getFileName().toString()).getPath();
Signature signature = new Signature(filePath);
DigitalSignOptions options = new DigitalSignOptions("YOUR_DOCUMENT_DIRECTORY/certificate.pfx");
options.setImageFilePath("YOUR_DOCUMENT_DIRECTORY/image.png");
options.setLeft(100);
options.setTop(100);
options.setPageNumber(1);
options.setPassword("1234567890");
SignResult result = signature.sign(outputFilePath, options);
System.out.println("Document signed successfully!");
System.out.println("Signatures applied: " + result.getSucceeded().size());
}
}
定義說明 – sign() 方法會在指定的輸出路徑產生新的已簽署 PDF,並回傳包含操作細節的 SignResult 物件。
要點:
- 原始 PDF 保持不變,會產生新檔案。
SignResult告知簽署是否成功,並提供簽章的中繼資料。
建議加入的錯誤處理:
try {
SignResult result = signature.sign(outputFilePath, options);
if (result.getSucceeded().size() > 0) {
System.out.println("Success! Signed document saved to: " + outputFilePath);
}
} catch (Exception e) {
System.err.println("Signing failed: " + e.getMessage());
e.printStackTrace();
}
常見陷阱與避免方法
在協助多位開發者實作 PDF 簽署後,以下是最常見的問題:
- 憑證路徑問題 – 使用絕對路徑或正確設定 classpath。
- 憑證密碼不符 – 再次確認 PFX 密碼,無法恢復。
- 輸出目錄不存在 – 先建立目錄:
new File(outputDirectory).mkdirs();
- 檔案已存在 – 選擇覆寫或產生帶版本號的檔名:
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String outputFile = "contract_signed_" + timestamp + ".pdf";
- 大型 PDF 記憶體問題 – 若 PDF 超過 50 MB,請增加 JVM 堆積 (
-Xmx512m或更高)。 - 憑證過期 – 簽署前驗證有效期限,過期憑證會產生無法驗證的簽章。
- 不支援的圖片格式 – GroupDocs 支援 PNG、JPG、BMP、GIF。請將不支援的格式轉為 PNG。
- 簽章位置超出頁面 – 確認座標在頁面尺寸內(A4 約 595 × 842 px,72 DPI)。
實務案例
1. 發票審批工作流程
情境:會計系統產生的 PDF 必須經過財務長批准,才能寄給客戶。
實作:產生發票,讓財務長點擊「批准」後套用數位簽章,將已簽署的 PDF 儲存,並自動寄送電郵。
重要性:提供不可變更的稽核紀錄,且免除手動列印/掃描。
2. 員工合約管理
情境:人資部門收集員工在勞動合約、保密協議與政策確認書上的簽名。
實作:上傳合約範本,員工點擊「接受」後系統套用員工的憑證,人資再加上自己的簽章,完整的文件即儲存於員工紀錄中。
效益:零紙本、即時時間戳記,且具法律約束力。
3. 自動文件認證
情境:驗證服務對原始文件的副本進行認證。
實作:上傳原件,套用帶有時間戳記與唯一驗證碼的可見「真實副本認證」印章,最後回傳已認證的 PDF。
結果:收件人可即時使用內嵌簽章驗證文件真偽。
4. 多方合約簽署
情境:房地產合約需要買方、賣方與仲介的簽名。
實作:第一方簽署後系統儲存 PDF,接著下一方載入已簽署的檔案再加入自己的簽章。GroupDocs 會保留所有既有簽章。
技術說明:使用新的 Signature 實例載入已簽署的 PDF,並重複簽署步驟。
安全最佳實踐
數位簽章的安全性取決於憑證管理。請遵循以下指引:
憑證儲存
- 絕不要 將
.pfx檔案提交至版本控制;請將*.pfx加入.gitignore。 - 絕不要 在公開的網站目錄中曝露憑證。
- 請 將憑證存放於專屬的祕密管理服務(如 AWS KMS、Azure Key Vault、HashiCorp Vault)。
- 使用環境變數保存密碼,並限制檔案權限(
chmod 600)。 - 在憑證過期前進行輪換,以維持信任度。
密碼管理
// Bad - hardcoded password
options.setPassword("1234567890");
// Better - environment variable
options.setPassword(System.getenv("CERT_PASSWORD"));
// Best - secure configuration management
options.setPassword(configService.getSecureValue("certificate.password"));
憑證驗證
// Check if certificate is still valid
X509Certificate cert = // load certificate
Date now = new Date();
if (now.before(cert.getNotBefore()) || now.after(cert.getNotAfter())) {
throw new Exception("Certificate is expired or not yet valid");
}
稽核日誌
logger.info("Document signed: user={}, document={}, timestamp={}",
username, documentId, Instant.now());
// Don't log: certificate passwords, full file paths, PII
效能考量
大量簽署 PDF 時,請留意以下建議:
記憶體管理
- 小型 PDF(< 10 MB) – 如上所示的記憶體內處理方式可完美運作。
- 大型 PDF(> 50 MB) – 考慮使用串流 API,避免一次載入整個檔案。
- 批次處理 – 當大量文件使用相同憑證簽署時,可重複使用單一
Signature實例。
串流示範說明(此處不使用程式碼區塊):使用 Signature 搭配 InputStream,將簽署後的輸出寫入 OutputStream,即可降低記憶體使用量。
處理時間基準(GroupDocs.Signature 23.12)
- 1‑5 頁 PDF(< 1 MB):200‑500 ms
- 20‑50 頁 PDF(5‑10 MB):1‑2 秒
- 100 頁以上 PDF(> 20 MB):3‑5 秒
上述數據假設使用標準 2.8 GHz CPU 與 8 GB 記憶體。
最佳化建議
- 只載入一次憑證,並在多個檔案間重複使用相同的
DigitalSignOptions。 - 使用 Java 的
ExecutorService以平行方式簽署獨立文件。 - 事先建立輸出目錄,以免在簽署迴圈內產生 I/O 延遲。
- 使用 VisualVM 等工具分析 JVM,找出真正的效能瓶頸。
疑難排解指南
「找不到憑證檔案」錯誤
症狀:在初始化 DigitalSignOptions 時拋出 FileNotFoundException。
解決方案:確認絕對路徑、檢查檔案權限,並使用 System.out.println(new File(".").getAbsolutePath()) 印出工作目錄。
「憑證密碼無效」錯誤
症狀:簽署過程中拋出例外。
解決方案:確認密碼正確(區分大小寫),確保與建立 PFX 時使用的密碼相同,若密碼遺失則重新產生憑證。
簽章出現在錯誤位置
症狀:可見簽章位置錯誤。
解決方案:記得座標以 (0,0) 左上角為起點。確認目標頁碼(首頁 = 1)。使用 setHorizontalAlignment() / setVerticalAlignment() 可獲得可靠的定位。
「簽署文件失敗」通用錯誤
症狀:出現含糊的錯誤訊息,無明確原因。
解決方案:透過 System.setProperty("com.groupdocs.signature.debug", "true") 開啟詳細日誌,確保 PDF 未損毀,檢查寫入權限,並驗證憑證是否有效。
PDF 閱讀器中看不到簽章
症狀:簽署成功卻未顯示視覺印章。
解決方案:確認 options.setImageFilePath(imagePath) 指向有效的 PNG/JPG,確保座標在頁面範圍內,並檢查閱讀器設定(部分閱讀器預設隱藏簽章)。
大型 PDF 記憶體不足(OutOfMemoryError)
症狀:JVM 當機或拋出 OutOfMemoryError。
解決方案:增加堆積大小(-Xmx1024m 或更高),分塊處理大型 PDF,並在使用完畢後立即關閉 Signature 物件。
常見問答
Q: 使用 GroupDocs.Signature for Java 的數位簽章有何好處?
A: 數位簽章具備法律可執行性、加密驗證、即時簽署(秒級而非天級),並提供完整稽核紀錄,顯示簽署者、時間與使用的憑證。GroupDocs 讓實作變得簡單,無需深厚 PDF 知識。
Q: 如何為我的專案選擇適當的 GroupDocs.Signature 版本?
A: 新專案建議使用最新的穩定版(目前為 23.12),可取得錯誤修正與效能提升。升級既有應用程式前請先檢視發行說明,以免產生相容性問題。
Q: 我能使用 GroupDocs.Signature 簽署非 PDF 文件嗎?
A: 當然可以。API 支援 Word、Excel、PowerPoint 以及常見圖片格式。相同的 Signature 與 DigitalSignOptions 類別可用於所有支援的類型。
Q: 能否自動化批次文件的簽署流程?
A: 可以。遍歷目錄,對每個檔案套用相同的 DigitalSignOptions,再儲存結果。高吞吐量情境下,可使用平行串流或 ExecutorService,並配置足夠的堆積記憶體。
Q: 如何驗證 PDF 是否已被數位簽署?
A: 在 Adobe Acrobat Reader 中開啟已簽署的 PDF,左側會出現簽章面板。點擊簽章即可查看憑證細節與驗證狀態。程式上,GroupDocs.Signature 也提供驗證 API。
Q: 開發、測試與正式環境需要不同的憑證嗎?
A: 需要。開發與測試可使用自簽憑證,正式環境則應取得 CA 簽發的憑證,以確保外部方的信任。
Q: 同一文件可以由多位人士簽署嗎?
A: 可以。載入已簽署的 PDF,新增 DigitalSignOptions 實例,再呼叫 sign()。每個簽章皆保留自己的時間戳記與憑證,形成完整的稽核紀錄。
結論
現在你已擁有完整且可投入生產的 在 Java 中建立 PDF 數位簽章 路線圖。從設定 GroupDocs.Signature、處理大型檔案、保護憑證,到批次作業的擴充,本指南讓你能在任何 Java 應用程式中嵌入可靠的電子簽署功能。
後續步驟
- 下載 GroupDocs.Signature 並使用免費試用版開始。
- 嘗試 各種外觀選項與座標設定。
- 整合 簽署流程至現有服務——API 端點、背景工作或 UI 操作。
- 探索進階功能,如 QR Code 簽章、條碼印章與中繼資料簽署。
提供的程式碼片段已可直接執行(只需替換佔位路徑與密碼)。加入完善的錯誤處理與安全的憑證儲存,即可在生產環境中自信地簽署 PDF。
Last Updated: 2026-06-11
Tested With: GroupDocs.Signature 23.12 for Java
Author: GroupDocs
// Good - explicit resource management
try (Signature signature = new Signature(filePath)) {
signature.sign(outputPath, options);
} // Automatically cleaned up