如何在 PDF 中使用 Java 建立條碼簽章
在本教學中,您將學習如何使用 Java 及 GroupDocs.Signature 建立條碼簽章於 PDF 檔案。條碼簽章嵌入機器可讀的識別碼,具備防篡改且易於掃描的特性——非常適合合約、證書、發票以及任何需要可靠驗證的文件。
快速解答
- 什麼是條碼簽章? 條碼嵌入於 PDF 中,儲存結構化資料,可由掃描器或軟件讀取。
- 建議使用哪種條碼類型? Code128,因為它能緊湊地處理字母與數字資料。
- 我需要授權嗎? 免費試用可用於測試;正式環境需購買完整授權。
- 我可以在任何頁面尺寸上放置條碼嗎? 可以——使用百分比定位以自動縮放。
- 條碼是向量圖形嗎? 是的,它只會在 PDF 中增加少量 KB,且在任何解析度下都保持清晰。
什麼是條碼簽章?
條碼簽章是一種向量條碼,直接嵌入於 PDF 頁面中,既作為視覺元素,又作為可稍後驗證的加密簽章。它儲存結構化資料,如 ID 或時間戳,確保文件完整性,同時提供機器可讀的參考。
為何條碼簽章對您的 PDF 重要
條碼簽章為 PDF 提供緊湊的機器可讀識別碼,可即時掃描,省去手動輸入資料並降低錯誤。由於以向量圖形嵌入,無論解析度如何都保持清晰,且僅增加少量 KB。這種可讀性、防篡改與小檔案大小的結合,使其非常適合合約、發票、證書以及任何需要可靠驗證的文件。
您可能曾遇到這樣的挑戰:需要在 PDF 中加入既機器可讀又防篡改的唯一識別碼。也許您正在開發文件管理系統、處理證書,或處理需要日後驗證的合約。
這正是條碼簽章發揮作用的地方。與簡單的文字印章不同,條碼可嵌入結構化資料,讓掃描器(以及您的軟件)即時讀取。此外,結合 GroupDocs.Signature for Java 的 PDF 簽署,您即可在不需複雜資料庫查詢的情況下,強力追蹤與驗證文件。
在本指南中,您將完整學會如何在 Java PDF 中實作條碼簽章——從基本設定到具彈性定位的生產就緒程式碼。無論您是構建發票系統、證書產生器或合約管理平台,最終都能掌握所需全部知識。
您將掌握:
- 在數分鐘內設定 GroupDocs.Signature for Java
- 建立 Code128 條碼簽章(以及為何它常是最佳選擇)
- 使用百分比布局定位條碼,適用於任何 PDF 大小
- 避免開發者常見的陷阱
- 正確測試您的實作
如何在 Java 中建立條碼簽章
在 Java 中建立條碼簽章的流程包括載入目標 PDF、設定條碼選項(如資料、類型、尺寸與位置),然後套用簽章以產生新文件。GroupDocs.Signature 會處理渲染與加密綁定,您只需提供所需參數並管理檔案路徑。
前置條件與環境清單
在開始之前,請確認您已備妥以下項目:
- Java Development Kit (JDK) 8 或更新版本 – 所有 GroupDocs Java 函式庫的必要條件。
- Maven 或 Gradle – 用於管理 GroupDocs.Signature 相依性。
- IDE(如 IntelliJ IDEA、Eclipse 或配有 Java 擴充功能的 VS Code)。
- GroupDocs.Signature for Java(建議使用 23.12 或更新版本)。
- 基本的 Java 知識 – 您應能熟練建立類別、處理例外以及使用檔案 I/O。
在專案中設定 GroupDocs.Signature
將函式庫加入專案相當簡單。選擇您的建置工具:
對於 Maven 使用者,在 pom.xml 中加入以下相依性:
<dependency>
<groupId>com.groupdocs</groupId>
<artifactId>groupdocs-signature</artifactId>
<version>23.12</version>
</dependency>
使用 Gradle 嗎? 在 build.gradle 中加入此行:
implementation 'com.groupdocs:groupdocs-signature:23.12'
偏好手動設定? 直接從 GroupDocs.Signature for Java releases 下載 JAR,並加入至 classpath。
取得授權設定
在正式投入生產前,您需要處理授權:
- 免費試用: 適合測試——可從 GroupDocs 官方網站取得,以探索核心功能。
- 臨時授權: 需要更多評估時間?可申請 30 天臨時授權。
- 完整授權: 已準備好投入生產?購買授權以獲得無限制使用。
以下是一個快速檢查,以確保一切正常運作:
Signature signature = new Signature("sample.pdf");
System.out.println("Signature object created successfully.");
如果執行無錯誤,即表示已完成設定!
如何在 Java 中建立條碼簽章
現在進入有趣的部分——讓我們為 PDF 加上條碼簽章。我們會將流程拆解為一步步的小步驟,讓您清楚了解每個階段的運作。
步驟 1:初始化 Signature 物件
定義說明: Signature 類別是 GroupDocs.Signature 用於載入、修改與儲存 PDF 文件的入口點。
首先,您需要告訴 GroupDocs 您正在處理哪個 PDF:
Signature signature = new Signature("input.pdf");
此程式碼的作用: Signature 物件會將您的 PDF 載入記憶體,並為後續修改做好準備。請確保檔案路徑正確——常見問題是 Windows 上使用單斜線而未轉義(請使用 \\ 或直接使用正斜線,跨平台皆可)。
步驟 2:設定條碼選項(如何新增條碼)
定義說明: BarcodeSignOptions 包含在 PDF 中呈現條碼所需的所有設定。
現在讓我們使用您的資料建立條碼簽章:
BarcodeSignOptions options = new BarcodeSignOptions("12345678");
options.setEncodeType(BarcodeEncodeType.Code128);
"12345678"為條碼資料——可作為訂單編號、證書號碼或任何您需要的識別碼。Code128為編碼類型(稍後會說明如何選擇合適的類型)。
專業提示: Code128 能同時處理數字與字母,適用於大多數情境。若僅需數字,Code39 可能較簡單,但 Code128 提供更高彈性。
步驟 3:定位條碼(如何以條碼簽署 PDF)
定義說明: SignatureOptions 提供版面屬性,如頁碼、尺寸與對齊方式。
這正是 GroupDocs 的優勢所在——使用百分比定位可確保條碼在任何 PDF 大小上皆顯示良好:
options.setLeft(10); // 10% from the left edge
options.setTop(90); // 90% from the bottom edge (near the footer)
options.setWidth(30); // 30% of page width
options.setHeight(10); // 10% of page height
options.setPageNumber(1);
為何使用百分比重要: 想像您同時簽署 A4 文件與 legal 大小的表單。使用百分比定位,條碼會自動縮放,兩者外觀一致。若使用固定像素值,條碼在大文件上會過小,或在小文件上過大。
實務範例: 在 A4 頁面(595 × 842 點)上,30% 寬度的條碼約為 180 點寬;在 legal 頁面(612 × 1008 點)上,約為 184 點寬——自動成比例。
步驟 4:簽署並儲存文件(如何在 PDF 中加入條碼)
現在正式套用簽章並儲存檔案:
signature.sign(outputPath, options);
重要說明: 輸出目錄必須事先存在。GroupDocs 不會自動建立子目錄,請先自行建立或在程式碼中處理:
new File("output").mkdirs();
如果發生錯誤該怎麼辦? 請將此段落放入 try‑catch 區塊:
try {
signature.sign("signed.pdf", options);
} catch (Exception e) {
e.printStackTrace();
}
為您的需求選擇合適的條碼類型(產生 Code128 條碼)
GroupDocs 支援多種條碼格式,選擇合適的類型相當重要。以下是實用比較:
Code128(我們的預設選擇):
- 適用情境: 混合字母與數字資料(如「INV2024-001」的 ID)
- 容量: 最多 128 個 ASCII 字元
- 為何優勝: 緊湊、廣泛支援,能同時處理字母與數字
- 使用時機: 需要彈性且不確定要編碼的資料類型時
Code39:
- 適用情境: 簡單的字母與數字碼
- 容量: 43 個字元(A‑Z、0‑9 以及部分符號)
- 考慮原因: 舊式掃描器通常較好支援
- 使用時機: 與舊系統整合或簡潔性比資料密度更重要時
QR Code:
- 適用情境: 大量資料(URL、JSON 內容)
- 容量: 最多 3 KB 資料
- 為何強大: 可儲存複雜資料結構,內建錯誤更正
- 使用時機: 需要嵌入結構化資料或 URL 時
EAN/UPC:
- 適用情境: 商品識別
- 容量: 固定長度數字碼(8‑13 位)
- 使用時機: 零售或庫存系統
快速決策指南:
- 需要字母與數字? → Code128
- 只需數字,保持簡單? → Code39
- 大量資料或 URL? → QR Code
- 零售/商品編碼? → EAN/UPC
常見陷阱與避免方法(防篡改條碼)
以下是開發者最常遇到的問題(讓您免於踩雷):
問題 1:條碼定位不正確
徵兆: 條碼出現在意外位置或被截斷。
常見原因:
- 在不同頁面尺寸上使用像素值
- 忘記 PDF 座標系統是從左下角開始,而非左上角
- 邊距將內容推至可視區域之外
解決方案: 為保持一致,請始終使用百分比定位:
options.setLeft(5);
options.setTop(95);
options.setWidth(40);
options.setHeight(12);
問題 2:條碼文字無法辨識
徵兆: 雖然條碼文字顯示,但掃描器無法讀取。
原因:
- 條碼尺寸對資料量而言過小
- 資料使用了錯誤的編碼類型
- 條與背景之間對比度不足
解決方案: 將條碼尺寸與資料長度匹配。對於 10‑15 個字元的 Code128,建議寬度至少佔頁面寬度的 8‑10%。
問題 3:檔案路徑例外
徵兆: FileNotFoundException 或類似錯誤。
原因:
- 使用單斜線的硬編碼 Windows 路徑
- 輸出目錄不存在
- 檔案權限問題
解決方案: 使用正斜線(跨平台皆可),並先建立目錄:
Path output = Paths.get("output/signed.pdf");
Files.createDirectories(output.getParent());
問題 4:大型 PDF 記憶體問題
徵兆: 處理大型文件時發生記憶體不足錯誤。
解決方案: 完成後關閉 Signature 物件以釋放資源:
signature.close();
測試您的條碼實作
部署前,請確保條碼實際可用。以下是實用測試清單:
1. 目視檢查測試
開啟已簽署的 PDF,檢查:
- 條碼是否可見且定位正確?
- 是否清晰(非模糊或像素化)?
- 周圍是否有足夠的留白?
2. 掃描測試
使用手機上的條碼掃描應用程式(如「Barcode Scanner」或「QR & Barcode Reader」)驗證:
- 掃描器能讀取條碼
- 解碼後的資料與您編碼的相符
- 能在不同角度與距離下讀取
3. 跨平台測試
在不同裝置上開啟您的 PDF:
- Windows(Adobe Reader、Chrome)
- Mac(Preview、Chrome)
- 行動裝置(iOS、Android)
確保條碼在所有平台上皆正確呈現。
4. 自動化測試程式碼
以下是一段簡易測試程式碼:
Signature testSignature = new Signature("signed.pdf");
List<BarcodeSignature> signatures = testSignature.search(BarcodeSignature.class);
if (signatures.size() > 0) {
System.out.println("Barcode found: " + signatures.get(0).getText());
}
條碼簽章的實務應用案例
讓我們看看此技術在實務系統中的亮點:
1. 證書產生與驗證
情境: 您正在建置一個發放結業證書的培訓平台。
實作方式: 產生唯一的證書 ID(例如「CERT‑2024‑00123」),並以 Code128 條碼嵌入右下角。掃描條碼即可讓 API 即時取得證書細節,省去手動輸入。
2. 發票追蹤系統
情境: 您的公司每月處理數千張發票。
實作方式: 將發票號碼與到期日以 QR code 形式加入,放置於掃描設備易於讀取的位置。自動分揀系統即可在無需人工介入的情況下處理發票,將處理時間從數小時縮短至數分鐘。
3. 法律合約管理
情境: 律師事務所需要追蹤合約版本與修訂。
實作方式: 每個合約版本皆附加包含合約 ID、版本號與簽署日期的唯一條碼識別碼。審核時掃描即可自動取得完整版本歷史。
4. 醫療紀錄安全
情境: 醫院希望防止未授權的紀錄存取。
實作方式: 在條碼中嵌入患者 ID 與紀錄建立時間戳。只有經驗證的裝置才能解碼並存取完整紀錄,且每次掃描都會產生合規審計日誌。
效能優化技巧(Java 文件安全)
簽署大量 PDF 時,效能相當重要。以下提供幾項讓系統順暢運作的技巧:
批次處理策略
與其一次簽署單一文件,不如批次處理:
for (String filePath : pdfList) {
Signature batchSignature = new Signature(filePath);
batchSignature.sign(outputPath, options);
batchSignature.close();
}
此做法的好處: 重複使用 options 物件並正確關閉資源,可防止記憶體洩漏。
大型 PDF 記憶體管理
針對大於 50 MB 的 PDF:
- 依序處理,而非一次載入多個。
- 使用 try‑with‑resources 確保資源釋放。
- 監控堆積大小,必要時調整 JVM 參數,例如
-Xmx2g。
快取常用條碼
若大量文件使用相同條碼,請快取 BarcodeSignOptions 實例:
BarcodeSignOptions cachedOptions = new BarcodeSignOptions("STATIC_ID");
cachedOptions.setEncodeType(BarcodeEncodeType.Code128);
何時使用條碼簽章(以及何時不適合)
理想情境:
- 需要機器可讀的文件識別碼。
- 文件將被自動掃描或處理。
- 想要防篡改追蹤,且不使用數位憑證。
- 需要與現有條碼基礎設施整合。
不適合的情況:
- 需要具法律效力的數位簽章(應改用數位憑證)。
- 文件僅供人類閱讀(簡單文字浮水印即可)。
- 文件極小,條碼會佔據過多版面。
- 安全需求要求加密——條碼是可見且任何人皆可掃描的。
可以結合兩種方式嗎? 當然可以!許多系統同時使用條碼簽章進行追蹤,並以數位簽章確保法律效力。
常見問答
Q: 我可以在同一個 PDF 中使用不同的條碼類型嗎?
A: 可以!對每種條碼類型呼叫 signature.sign() 多次,使用不同的 BarcodeSignOptions。只要確保它們不重疊即可。
Q: 如何處理包含特殊字元的條碼?
A: Code128 能良好處理大多數 ASCII 字元。若需 Unicode 或複雜資料,請改用 QR code——支援 UTF‑8 編碼。
Q: Code128 條碼最多能儲存多少資料?
A: 理論上可達 128 個字元,但超過 30‑40 個字元可讀性會顯著下降。若資料較大,請使用 QR code。
Q: 加入條碼會顯著增加 PDF 檔案大小嗎?
A: 不會明顯增加——條碼為向量圖形,通常僅增加 5‑20 KB(視尺寸與複雜度而定)。
Q: 我可以旋轉條碼或垂直放置嗎?
A: 可以!使用 options.setRotationAngle(90) 旋轉條碼,適合放置於邊緣。
Q: 如何讓條碼出現在多頁 PDF 的每一頁?
A: 迭代頁面,對每頁套用簽章。請參考 GroupDocs 文件中的 PagesSetup 類別,以控制簽署的頁面。
Q: 若條碼掃描器無法讀取產生的條碼該怎麼辦?
A: 首先確認掃描器支援所選條碼類型。接著增大條碼尺寸——大多數掃描問題源於條碼過小。建議寬度至少 1 吋(2.54 cm)以確保可靠讀取。
其他資源
文件說明:
下載與授權:
社群與支援:
- 支援論壇 - 活躍社群與 GroupDocs 工程師
最後更新: 2026-07-20
測試環境: GroupDocs.Signature 23.12(Java)
作者: GroupDocs
<dependency>
<groupId>com.groupdocs</groupId>
<artifactId>groupdocs-signature</artifactId>
<version>23.12</version>
</dependency>
implementation 'com.groupdocs:groupdocs-signature:23.12'
import com.groupdocs.signature.Signature;
public class QuickTest {
public static void main(String[] args) {
try {
Signature signature = new Signature("test-document.pdf");
System.out.println("GroupDocs.Signature is ready to go!");
} catch (Exception e) {
System.err.println("Setup issue: " + e.getMessage());
}
}
}
String filePath = "YOUR_DOCUMENT_DIRECTORY/sample.pdf";
Signature signature = new Signature(filePath);
import com.groupdocs.signature.options.sign.BarcodeSignOptions;
import com.groupdocs.signature.domain.barcodes.BarcodeTypes;
BarcodeSignOptions options = new BarcodeSignOptions("12345678");
options.setEncodeType(BarcodeTypes.Code128);
import com.groupdocs.signature.domain.enums.MeasureType;
import com.groupdocs.signature.domain.Padding;
// Use percentages instead of fixed pixels
options.setLocationMeasureType(MeasureType.Percents);
options.setLeft(5); // 5% from the left edge
options.setTop(5); // 5% from the top
// Size it proportionally too
options.setSizeMeasureType(MeasureType.Percents);
options.setWidth(10); // 10% of page width
options.setHeight(5); // 5% of page height
// Add some breathing room with margins
Padding margins = new Padding();
margins.setLeft(1);
margins.setTop(1);
margins.setRight(1);
options.setMargin(margins);
String outputFilePath = "YOUR_OUTPUT_DIRECTORY/SignWithPercents/sample_signed.pdf";
signature.sign(outputFilePath, options);
Path outputPath = Paths.get(outputFilePath);
Files.createDirectories(outputPath.getParent());
signature.sign(outputFilePath, options);
try {
signature.sign(outputFilePath, options);
System.out.println("PDF signed successfully at: " + outputFilePath);
} catch (Exception e) {
System.err.println("Signing failed: " + e.getMessage());
e.printStackTrace();
}
options.setLocationMeasureType(MeasureType.Percents);
options.setLeft(5); // 5% from left works on any page width
options.setWidth(10); // Give it room to breathe
options.setHeight(5); // Maintain proper aspect ratio
String filePath = "documents/sample.pdf"; // Works on Windows, Mac, Linux
Files.createDirectories(Paths.get("output/signed"));
try (Signature signature = new Signature(filePath)) {
signature.sign(outputFilePath, options);
} // Automatically closes and releases memory
import org.junit.Test;
import static org.junit.Assert.*;
public class BarcodeSignatureTest {
@Test
public void testBarcodeSigning() {
String testPdf = "test-data/sample.pdf";
String output = "test-output/signed.pdf";
try (Signature signature = new Signature(testPdf)) {
BarcodeSignOptions options = new BarcodeSignOptions("TEST123");
options.setEncodeType(BarcodeTypes.Code128);
signature.sign(output, options);
// Verify output file exists
assertTrue(new File(output).exists());
// Verify file size increased (signature was added)
long originalSize = new File(testPdf).length();
long signedSize = new File(output).length();
assertTrue(signedSize > originalSize);
} catch (Exception e) {
fail("Signing should not throw exception: " + e.getMessage());
}
}
}
List<String> pdfFiles = Arrays.asList("doc1.pdf", "doc2.pdf", "doc3.pdf");
for (String pdfFile : pdfFiles) {
try (Signature signature = new Signature(pdfFile)) {
BarcodeSignOptions options = createBarcodeOptions(); // Reuse options
signature.sign(getOutputPath(pdfFile), options);
}
}
// Create options once, reuse many times
BarcodeSignOptions templateOptions = createStandardBarcodeOptions();
// For each document, clone and customize
BarcodeSignOptions documentOptions = templateOptions.clone();
documentOptions.setText(uniqueDocumentId);