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

iText 在現有 PDF 追加內容實戰:文件拷貝流、PdfStamper 與繪圖完整指南

     編輯:Java 相關知識

核心挑戰

PdfReader 讀取 PDF 後會鎖定文件,**無法直接寫回原文件**。必須「讀取副本 → 寫入原路徑」或「寫入新路徑 → 替換」。

推薦方案:管道流拷貝 + PdfStamper 就地更新


import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import java.io.*;
import java.nio.channels.FileChannel;

public class PdfAppender {
    public static void appendContent(String pdfPath) throws Exception {
        File src = new File(pdfPath);
        File tmp = new File(pdfPath + ".tmp");

        // 1. 高效拷貝:NIO 管道流,零用戶態拷貝
        fileChannelCopy(src, tmp);

        // 2. 讀取副本,寫回原文件
        PdfReader reader = new PdfReader(tmp.getAbsolutePath());
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(src));

        // 3. 獲取第 1 頁的「上層」繪圖畫布 (疊加在現有內容之上)
        PdfContentByte over = stamper.getOverContent(1);

        // --- 追加文字 ---
        BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        over.beginText();
        over.setFontAndSize(font, 12);
        over.setTextMatrix(200, 700); // 底部座標 (左下角原點)
        over.showText("追加的水印文字");
        over.endText();

        // --- 追加圖片 ---
        Image img = Image.getInstance("logo.png");
        img.setAbsolutePosition(100, 600);
        over.addImage(img);

        // --- 繪製紅色圓圈 ---
        over.setRGBColorStroke(0xFF, 0x00, 0x00);
        over.setLineWidth(2f);
        over.ellipse(250, 450, 350, 550); // 外接矩形
        over.stroke();

        stamper.close();
        reader.close();

        // 4. 清理臨時文件
        tmp.delete();
    }

    // NIO 管道拷貝:極快、內存友好
    public static void fileChannelCopy(File src, File dest) throws IOException {
        try (FileInputStream in = new FileInputStream(src);
             FileOutputStream out = new FileOutputStream(dest);
             FileChannel inCh = in.getChannel();
             FileChannel outCh = out.getChannel()) {
            inCh.transferTo(0, inCh.size(), outCh);
        }
    }
}

關鍵 API 速查

類/方法用途
PdfReader解析現有 PDF 結構
PdfStamper(reader, os)基於 reader 向輸出流寫入修訂
getOverContent(pageNum)獲取頁面**上層**畫布 (疊加模式)
getUnderContent(pageNum)獲取頁面**下層**畫布 (背景水印模式)
BaseFont.createFont註冊中文字體 (需 iTextAsian.jar)
PdfContentByte 繪圖文字/圖片/幾何圖形/路徑構建

避坑指南

  • 字體註冊:中文必須使用 STSong-Light + UniGB-UCS2-H 且引入 itext-asian 依賴,否則顯示方塊。
  • 座標系統:PDF 原點在**頁面左下角**,X 向右、Y 向上,單位 = 1/72 英寸 (pt)。
  • 臨時文件清理:finally 塊確保 .tmp 刪除,防止磁盤洩漏。
  • 大文件處理:超大 PDF 考慮 PdfReader.unethicalreading = true 或分頁增量處理。

iText 5.x 核心思想:**增量更新**。原 PDF 結構不變,僅在末尾追加修訂區 (xref 表)。理解這一點,就明白為什麼必須「讀副本寫原文」——避免同一文件同時被 Reader 和 OutputStream 佔用導致損壞。

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