在指定的pdf模版中指定坐标位置添加内容

package org.example.pdf;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 在指定的pdf模版中指定坐标位置添加内容
 */
public class PdfTemplateFiller {

    // 文本位置定义类
    public static class TextPosition {
        private int pageNumber;
        private float x;
        private float y;
        private String text;
        private PDFont font;
        private float fontSize;

        public TextPosition(int pageNumber, float x, float y, String text) {
            this.pageNumber = pageNumber;
            this.x = x;
            this.y = y;
            this.text = text;
            this.font = PDType1Font.HELVETICA; // 默认字体
            this.fontSize = 12; // 默认字体大小
        }

        public TextPosition(int pageNumber, float x, float y, String text, PDFont font, float fontSize) {
            this.pageNumber = pageNumber;
            this.x = x;
            this.y = y;
            this.text = text;
            this.font = font;
            this.fontSize = fontSize;
        }

        // Getter和Setter方法
        public int getPageNumber() { return pageNumber; }
        public void setPageNumber(int pageNumber) { this.pageNumber = pageNumber; }
        public float getX() { return x; }
        public void setX(float x) { this.x = x; }
        public float getY() { return y; }
        public void setY(float y) { this.y = y; }
        public String getText() { return text; }
        public void setText(String text) { this.text = text; }
        public PDFont getFont() { return font; }
        public void setFont(PDFont font) { this.font = font; }
        public float getFontSize() { return fontSize; }
        public void setFontSize(float fontSize) { this.fontSize = fontSize; }
    }

    /**
     * 在PDF模板的指定位置添加文本
     * @param inputPdfPath 输入PDF路径
     * @param outputPdfPath 输出PDF路径
     * @param textPositions 文本位置列表
     * @param fontPath 中文字体路径(可选,如果不需要中文可传null)
     */
    public static void fillPdfTemplate(String inputPdfPath, String outputPdfPath,
                                       List<TextPosition> textPositions, String fontPath) throws IOException {
        // 加载PDF文档
        PDDocument document = PDDocument.load(new File(inputPdfPath));

        // 加载中文字体(如果需要)
        PDFont chineseFont = null;
        if (fontPath != null && !fontPath.isEmpty()) {
            chineseFont = PDType0Font.load(document, new File(fontPath));
        }

        // 处理每一页
        for (int i = 0; i < document.getNumberOfPages(); i++) {
            PDPage page = document.getPage(i);
            PDRectangle pageSize = page.getMediaBox();

            // 获取当前页需要添加的所有文本
            List<TextPosition> pageTexts = new ArrayList<>();
            for (TextPosition tp : textPositions) {
                if (tp.getPageNumber() == i) {
                    pageTexts.add(tp);
                }
            }

            if (!pageTexts.isEmpty()) {
                // 创建内容流
                try (PDPageContentStream contentStream = new PDPageContentStream(
                        document, page, PDPageContentStream.AppendMode.APPEND, true, true)) {

                    // 添加所有文本
                    for (TextPosition tp : pageTexts) {
                        PDFont fontToUse = tp.getFont();

                        // 如果指定了中文字体且文本包含中文,使用中文字体
                        if (chineseFont != null && containsChinese(tp.getText())) {
                            fontToUse = chineseFont;
                        }

                        contentStream.beginText();
                        contentStream.setFont(fontToUse, tp.getFontSize());
                        contentStream.newLineAtOffset(tp.getX(), pageSize.getHeight() - tp.getY());
                        contentStream.showText(tp.getText());
                        contentStream.endText();
                    }
                }
            }
        }

        // 保存文档
        document.save(outputPdfPath);
        document.close();
    }

    /**
     * 检查字符串是否包含中文字符
     */
    private static boolean containsChinese(String text) {
        return text.chars().anyMatch(c ->
                Character.UnicodeScript.of(c) == Character.UnicodeScript.HAN);
    }

    /**
     * 示例用法
     */
    public static void main(String[] args) {
        try {
            // 准备要添加的文本位置
            List<TextPosition> textPositions = new ArrayList<>();

            // 第一页的文本
            textPositions.add(new TextPosition(0, 731, 460, "姓名: 张三"));
            textPositions.add(new TextPosition(0, 100, 680, "年龄: 30"));

            // 第二页的文本
            textPositions.add(new TextPosition(1, 100, 500, "部门: 技术部"));
            textPositions.add(new TextPosition(1, 100, 480, "职位: 工程师"));

            // 如果需要使用中文字体,指定字体文件路径
            // 黑体字体路径
            String fontPath = "C:/Windows/Fonts/simhei.ttf";
            // 填充PDF模板
            fillPdfTemplate("C:\\Users\\50649\\Desktop\\测试pdf\\output2.pdf", "C:\\Users\\50649\\Desktop\\测试pdf\\filled_template.pdf", textPositions, fontPath);

            System.out.println("PDF填充完成!");
        } catch (IOException e) {
            System.err.println("处理PDF时发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

 导入依赖

 <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.27</version>
        </dependency>

 

posted @ 2025-09-10 11:44  红尘沙漏  阅读(21)  评论(0)    收藏  举报