首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 生成 PDF 實戰:iText 核心 API、章節結構、樣式與中文支持完整指南

     編輯:Java 程式設計入門

技術選型:iText 版本說明

代碼示例使用 iText 2.1.7 (com.lowagie),該版本為 LGPL/MPL 雙許可,最后開源版本。iText 5+ (com.itextpdf) 為商業閉源,需購買許可。開源替代方案:Apache PDFBox、OpenPDF (iText 4 分支)。本文以 iText 2.1.7 為例,核心 API 思路通用。

Maven 依賴

<dependency>
    <groupId>com.lowagie</groupId>
    <artifactId>itext</artifactId>
    <version>2.1.7</version>
</dependency>

<dependency>
    <groupId>com.lowagie</groupId>
    <artifactId>itext-asian</artifactId>
    <version>2.1.7</version>
</dependency>

核心類職責

  • Document:文檔模型,設置頁面大小、邊距。
  • PdfWriter:將 Document 寫入 OutputStream,綁定輸出目標。
  • Paragraph:文本塊,可設置字體、顏色、對齊、間距。
  • Chapter/Section:層級結構,自動生成書籤、目錄。
  • FontFactory:字體工廠,註冊 TTF 字體文件支持中文。
  • PdfPTable/PdfPCell:表格佈局。
  • Image:圖片嵌入。

示例 1:最簡單的 Hello World

public static void simplePdf(String dest) throws Exception {
    Document doc = new Document(PageSize.A4, 50, 50, 50, 50);
    PdfWriter.getInstance(doc, new FileOutputStream(dest));
    doc.open();
    doc.add(new Paragraph("Hello PDF!"));
    doc.close();
}

示例 2:帶章節、樣式、中文、表格的完整報表

public static void complexReport(String dest) throws Exception {
    // 1. 註冊中文字體 (需 itext-asian 或手動註冊 TTF)
    FontFactory.register("C:/Windows/Fonts/msyh.ttc", "Microsoft YaHei");
    Font chineseFont = FontFactory.getFont("Microsoft YaHei", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 12);
    Font titleFont = new Font(chineseFont.getBaseFont(), 18, Font.BOLDITALIC, BaseColor.BLUE);
    Font sectionFont = new Font(chineseFont.getBaseFont(), 14, Font.BOLD, BaseColor.RED);

    Document doc = new Document(PageSize.A4, 36, 36, 54, 36);
    PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream(dest));
    
    // 可選:頁眉頁腳事件
    writer.setPageEvent(new HeaderFooterEvent());

    doc.open();
    // 元數據
    doc.addTitle("銷售報表");
    doc.addAuthor("系統自動生成");
    doc.addSubject("2024 Q1");
    doc.addKeywords("PDF, iText, Report");
    doc.addCreator("Java App");

    // 標題
    Paragraph title = new Paragraph("2024 年第一季度銷售報表", titleFont);
    title.setAlignment(Element.ALIGN_CENTER);
    title.setSpacingAfter(20);
    doc.add(title);

    // 章節 1
    Chapter chapter1 = new Chapter(new Paragraph("1. 總體概況", sectionFont), 1);
    chapter1.setNumberDepth(0); // 不顯示章節編號
    
    Section sec1 = chapter1.addSection(new Paragraph("1.1 關鍵指標", new Font(chineseFont.getBaseFont(), 12, Font.BOLD)));
    sec1.add(new Paragraph("本季度總銷售額達 1.2 億元,同比增長 15%。", chineseFont));
    
    // 表格
    PdfPTable table = new PdfPTable(new float[]{2, 1, 1, 1});
    table.setWidthPercentage(100);
    addTableHeader(table, chineseFont, "月份", "銷售額(萬)", "訂單數", "客單價");
    addTableRow(table, chineseFont, "1月", "350", "1200", "291");
    addTableRow(table, chineseFont, "2月", "420", "1450", "289");
    addTableRow(table, chineseFont, "3月", "430", "1500", "286");
    sec1.add(table);
    
    doc.add(chapter1);

    // 章節 2 - 新頁
    doc.newPage();
    Chapter chapter2 = new Chapter(new Paragraph("2. 區域明細", sectionFont), 2);
    // ... 類似添加內容
    doc.add(chapter2);

    doc.close();
}

private static void addTableHeader(PdfPTable table, Font font, String... headers) {
    for (String h : headers) {
        PdfPCell cell = new PdfPCell(new Phrase(h, font));
        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setPadding(5);
        table.addCell(cell);
    }
}

private static void addTableRow(PdfPTable table, Font font, String... cols) {
    for (String c : cols) {
        PdfPCell cell = new PdfPCell(new Phrase(c, font));
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setPadding(5);
        table.addCell(cell);
    }
}

頁眉頁腳事件實現

class HeaderFooterEvent extends PdfPageEventHelper {
    Font font = FontFactory.getFont(FontFactory.HELVETICA, 8, Font.NORMAL, BaseColor.GRAY);
    @Override
    public void onEndPage(PdfWriter writer, Document doc) {
        PdfContentByte cb = writer.getDirectContent();
        // 頁碼
        ColumnText.showTextAligned(cb, Element.ALIGN_CENTER,
            new Phrase(String.format("第 %d 頁", writer.getPageNumber()), font),
            (doc.right() - doc.left()) / 2 + doc.leftMargin(),
            doc.bottomMargin() - 10, 0);
        // 頁眉
        ColumnText.showTextAligned(cb, Element.ALIGN_LEFT,
            new Phrase("機密文檔", font),
            doc.left(), doc.top() + 10, 0);
    }
}

中文支持關鍵點

  1. 字體嵌入:`BaseFont.IDENTITY_H` + `BaseFont.EMBEDDED` 確保 PDF 內嵌字體,跨平台顯示一致。
  2. 字體註冊:`FontFactory.register("path/to/msyh.ttc", "alias")` 或放入 `itext-asian.jar` 使用 `STSong-Light`、`MSung-Light` 等預置字體。
  3. TTF/TTC 選擇:微軟雅黑 `msyh.ttc` 包含常規/粗體,單文件解決多字重。

常見問題與優化

問題解決方案
中文顯示 □/亂碼未嵌入字體或字體不支持該字符;檢查 FontFactory.register 路徑、BaseFont.IDENTITY_H、EMBEDDED
大文件 OOM使用 `PdfWriter.setFullCompression()`、分頁寫入、避免一次性載入大量數據到內存
表格跨頁斷裂`table.setSplitLate(false)`、`cell.setNoWrap(false)`、設置 `setKeepTogether(false)`
性能優化複用 Font 對象、關閉不必要的調試日志、大批量數據考慮 PDFBox 流式寫入
數字簽名/水印使用 `PdfStamper` 簽名、`PdfContentByte` 繪制水印

遷移建議:iText 5/7 或 OpenPDF

若項目無法承擔商業許可,建議遷移至 OpenPDF (groupId: com.github.librepdf, artifactId: openpdf),API 與 iText 2.1.7 高度兼容,僅包名變為 `com.lowagie` → `com.lowagie` (同包名) 或 `com.itextpdf` (iText 5+)。遷移步驟:替換依賴、修正包導入、測試中文表格分頁。

總結

iText 以強大的佈局引擎、豐富的 PDF 操作 API(表格、書籤、簽名、加密、表單)成為 Java 生態 PDF 生成首選。掌握 Document/Writer/Paragraph/Chapter/Table/Font 核心組件協作,配合中文字體嵌入、頁面事件、流式寫入技巧,可構建專業級報表、合同、發票生成系統。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved