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

Java iText 7 生成 PDF 完整實戰教程

     編輯:Java 相關知識

iText 版本選擇

  • iText 5:舊版,Maven Central 可用,AGPL 協議
  • iText 7:現代模塊化架構,com.itextpdf:itext7-core:7.2.5,AGPL/商業雙授權
  • OpenPDF:iText 5 LGPL 分支,com.github.librepdf:openpdf:1.3.35,免費商用

本文基於 iText 7 演示,核心包:kernel、layout、io。

Maven 依賴

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext7-core</artifactId>
    <version>7.2.5</version>
    <type>pom</type>
</dependency>

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>font-asian</artifactId>
    <version>7.2.5</version>
</dependency>

場景一:創建基礎 PDF 文檔

import com.itextpdf.kernel.pdf.*;
import com.itextpdf.layout.*;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.properties.*;
import java.io.*;

public class BasicPdf {
    public static void main(String[] args) throws IOException {
        String dest = "basic.pdf";
        // 1. PdfWriter
        PdfWriter writer = new PdfWriter(dest);
        // 2. PdfDocument
        PdfDocument pdfDoc = new PdfDocument(writer);
        // 3. Document (高層布局)
        Document document = new Document(pdfDoc);

        // 文檔元數據
        pdfDoc.getDocumentInfo().setTitle("iText 7 Demo");
        pdfDoc.getDocumentInfo().setAuthor("Developer");
        pdfDoc.getDocumentInfo().setSubject("Basic Example");
        pdfDoc.getDocumentInfo().setKeywords("iText, PDF, Java");

        // 4. 添加內容
        document.add(new Paragraph("Hello World!")
            .setFontSize(24)
            .setBold()
            .setTextAlignment(TextAlignment.CENTER)
            .setMarginTop(100));

        document.add(new Paragraph("這是使用 iText 7 生成的第一個 PDF 文檔。")
            .setFontSize(14)
            .setMarginTop(20));

        // 5. 關閉 (自動 flush)
        document.close();
        System.out.println("PDF 生成完成: " + dest);
    }
}

場景二:複雜表格製作

public class TablePdf {
    public static void main(String[] args) throws IOException {
        PdfWriter writer = new PdfWriter("table.pdf");
        PdfDocument pdfDoc = new PdfDocument(writer);
        Document document = new Document(pdfDoc);

        // 創建 3 列表格
        Table table = new Table(3).useAllAvailableWidth();
        
        // 表頭
        table.addHeaderCell(new Cell().add(new Paragraph("ID")).setBold().setBackgroundColor(ColorConstants.LIGHT_GRAY));
        table.addHeaderCell(new Cell().add(new Paragraph("名稱")).setBold().setBackgroundColor(ColorConstants.LIGHT_GRAY));
        table.addHeaderCell(new Cell().add(new Paragraph("價格")).setBold().setBackgroundColor(ColorConstants.LIGHT_GRAY));

        // 數據行
        String[][] data = {
            {"1", "蘋果", "¥5.00"},
            {"2", "香蕉", "¥3.50"},
            {"3", "橙子", "¥4.20"}
        };
        for (String[] row : data) {
            for (String cell : row) {
                table.addCell(new Cell().add(new Paragraph(cell)));
            }
        }

        // 跨列合併
        table.addCell(new Cell(1, 3).add(new Paragraph("總計: 3 種水果")).setTextAlignment(TextAlignment.CENTER));

        document.add(table);
        document.close();
    }
}

場景三:圖片與絕對定位文字

public class ImagePdf {
    public static void main(String[] args) throws IOException {
        // A4 橫向,邊距 0
        PageSize pageSize = PageSize.A4.rotate();
        PdfWriter writer = new PdfWriter("image.pdf");
        PdfDocument pdfDoc = new PdfDocument(writer);
        pdfDoc.setDefaultPageSize(pageSize);
        Document document = new Document(pdfDoc, pageSize);
        document.setMargins(0, 0, 0, 0);

        // 背景圖片鋪滿
        Image bg = new Image(ImageDataFactory.create("bg.jpg"))
            .setFixedPosition(0, 0)
            .scaleToFit(pageSize.getWidth(), pageSize.getHeight());
        document.add(bg);

        // 絕對定位文字 (使用 Canvas 底層 API)
        PdfCanvas canvas = new PdfCanvas(pdfDoc.getFirstPage());
        PdfFont font = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED);
        
        canvas.beginText()
              .setFontAndSize(font, 12)
              .moveText(100, 500)
              .showText("坐標 (100, 500) 的中文文字")
              .endText();

        // 批量繪製網格座標
        canvas.beginText().setFontAndSize(font, 8);
        for (int y = 0; y <= pageSize.getHeight(); y += 50) {
            for (int x = 0; x <= pageSize.getWidth(); x += 50) {
                canvas.moveText(x, y).showText(String.format("(%d,%d)", x, y));
            }
        }
        canvas.endText();

        document.close();
    }
}

中文字體解決方案

方案適用場景代碼示例
font-asian 模塊簡體/繁體/日/韓,無需字體文件PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H")
本地 TTF 字體特定字體要求、商業項目PdfFontFactory.createFont("msyh.ttf", PdfEncodings.IDENTITY_H, true)
系統字體註冊動態加載系統字體FontProgramFactory.registerSystemFonts(); 後用字體名

進階功能速覽

  • 水印:PdfCanvas 繪製半透明文字/圖片,或 PdfPageEventForwarder 頁面事件
  • 數字簽名:PdfSigner + 憑證鏈,支持 PAdES-LTV
  • 表單填充:PdfAcroForm 獲取字段 setValue()
  • HTML 轉 PDF:pdfHTML 模塊 HtmlConverter.convertToPdf()
  • PDF/A 合規:PdfADocument 創建歸檔級 PDF
  • 大文件流式:PdfWriter.setSmartMode(true) + 分頁寫入

常見問題排查

問題解決
中文顯示方框/亂碼未註冊中文字體,用 font-asian 或本地 TTF
表格跨頁斷裂table.setSplitLate(false) 或調整 setKeepTogether(true)
圖片模糊/變形scaleToFit() 保持比例,避免 setFixedPosition 強制拉伸
內存溢出大文檔用 PdfWriter.setSmartMode(true),分批 document.flush()
AGPL 合規商業閉源項目需購買授權,或遷移 OpenPDF

總結

iText 7 通過 PdfDocument (底層) + Document (高層布局) 分離關注點,功能強大但學習曲線較陡。核心掌握:字體註冊、表格佈局、Canvas 底層繪圖、流式處理大文件。中文項目優先用 font-asian 解決字體問題。商業項目注意 AGPL 協議,評估 OpenPDF 或購買授權。

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