You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iTextSharp中PdfCopy下如何添加页眉PDF?原方案致字符串替换失效

解决用iText添加页眉且不破坏PDF格式的方案

Hey,我刚好遇到过类似的问题!之前用PdfContentByte.addTemplate加页眉时,确实容易破坏原PDF的内部结构,导致后续的字符串替换这类依赖文档结构的功能失效。改用PdfCopy或者PdfSmartCopy是非常正确的思路,我来给你详细讲怎么实现:

核心思路

我们的目标是完整保留原内容PDF的结构,同时将页眉PDF的内容合并到每个内容页面的顶部。实现方式是:

  • 将页眉PDF的页面转换为可复用的模板(Form XObject)
  • 遍历内容PDF的每个页面,创建新页面后先绘制页眉模板,再绘制原内容页面的模板
  • 全程基于页面的完整拷贝操作,不修改原内容的内部流结构

实现代码(iText 7)

iText 7的API更简洁,类型安全也更好,以下是完整示例:

import com.itextpdf.kernel.pdf.*;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;

import java.io.IOException;

public class AddHeaderToPdf {
    public static void main(String[] args) throws IOException {
        // 替换为你的文件路径
        String headerPdfPath = "header.pdf";
        String contentPdfPath = "content.pdf";
        String outputPdfPath = "output_with_header.pdf";

        // 初始化文档对象
        PdfDocument headerDoc = new PdfDocument(new PdfReader(headerPdfPath));
        PdfDocument contentDoc = new PdfDocument(new PdfReader(contentPdfPath));
        PdfDocument outputDoc = new PdfDocument(new PdfWriter(outputPdfPath));

        // 将页眉页面转为可复用模板(假设页眉只有1页)
        PdfPage headerPage = headerDoc.getPage(1);
        PdfFormXObject headerTemplate = headerPage.copyAsFormXObject(outputDoc);
        Rectangle headerSize = headerPage.getPageSize();
        float headerHeight = headerSize.getHeight();

        // 遍历处理每个内容页面
        for (int pageNum = 1; pageNum <= contentDoc.getNumberOfPages(); pageNum++) {
            PdfPage contentPage = contentDoc.getPage(pageNum);
            Rectangle contentSize = contentPage.getPageSize();

            // 创建新页面,尺寸为内容页面高度 + 页眉高度(也可以保持原尺寸,页眉覆盖顶部)
            Rectangle newPageSize = new Rectangle(contentSize.getWidth(), contentSize.getHeight() + headerHeight);
            PdfPage newPage = outputDoc.addNewPage(newPageSize);

            // 绘制页眉到新页面顶部
            PdfCanvas canvas = new PdfCanvas(newPage);
            canvas.addXObject(headerTemplate, 0, contentSize.getHeight());

            // 绘制原内容页面到页眉下方
            PdfFormXObject contentTemplate = contentPage.copyAsFormXObject(outputDoc);
            canvas.addXObject(contentTemplate, 0, 0);
        }

        // 关闭所有资源
        headerDoc.close();
        contentDoc.close();
        outputDoc.close();
    }
}

实现代码(iText 5)

如果还在使用iText 5,代码逻辑类似,但API略有不同:

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;

import java.io.FileOutputStream;
import java.io.IOException;

public class AddHeaderWithPdfCopy {
    public static void main(String[] args) throws IOException, DocumentException {
        String headerPath = "header.pdf";
        String contentPath = "content.pdf";
        String outputPath = "output_with_header.pdf";

        PdfReader headerReader = new PdfReader(headerPath);
        PdfReader contentReader = new PdfReader(contentPath);
        Document document = new Document();
        PdfCopy pdfCopy = new PdfCopy(document, new FileOutputStream(outputPath));

        document.open();

        // 获取页眉页面并转为模板
        PdfImportedPage headerPage = pdfCopy.getImportedPage(headerReader, 1);
        Rectangle headerRect = headerPage.getBoundingBox();
        float headerHeight = headerRect.getHeight();

        // 处理每个内容页面
        for (int i = 1; i <= contentReader.getNumberOfPages(); i++) {
            PdfImportedPage contentPage = pdfCopy.getImportedPage(contentReader, i);
            Rectangle contentRect = contentPage.getBoundingBox();

            // 设置新页面尺寸
            document.setPageSize(new Rectangle(contentRect.getWidth(), contentRect.getHeight() + headerHeight));
            document.newPage();

            // 获取画布,先绘制页眉,再绘制内容
            PdfContentByte canvas = pdfCopy.getDirectContent();
            canvas.addTemplate(headerPage, 0, contentRect.getHeight());
            canvas.addTemplate(contentPage, 0, 0);
        }

        // 关闭资源
        document.close();
        headerReader.close();
        contentReader.close();
    }
}

关键说明

  • 为什么这个方案不会破坏格式?因为我们是将原内容页面完整拷贝为PdfFormXObject(iText7)或PdfImportedPage(iText5),没有修改原页面的内部内容流,所以原PDF的表单、可搜索文本、字符串替换标记等结构都能完整保留。
  • 如果页眉有多页,可以根据需求调整逻辑(比如只取第一页作为页眉,或者循环使用不同页眉)。
  • PdfSmartCopy和PdfCopy的用法几乎一致,PdfSmartCopy会自动复用重复的内容,生成的PDF体积更小,你可以直接把代码里的PdfCopy换成PdfSmartCopy即可。

内容的提问来源于stack exchange,提问作者Shahid Huss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:14:09