Java操作PDF(动态文本/图片添加,定位横纵坐标,偏移量添加字符)

一、前言

        本篇文章是实现填充PDF模板并生成图片,代码中使用到根据占位符添加文本和图片,以及根据横纵坐标,偏移量添加勾选“√”,大佬们有不足的地方可直接指出,java萌新成长之路

二、PDF准备

        通过第三方工具给我们的PDF添加输入框并标记占位符,修改完成后直接保存下载

三、依赖

        <!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <!-- iText -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13.2</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>kernel</artifactId>
            <version>7.1.16</version> <!-- Use the version that suits your project -->
        </dependency>
        <!-- pdfbox -->
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.24</version>
        </dependency>

四、测试demo

  1)测试方法

    public static void main(String[] args) {
        String basePath = "D:\\storage\\pdf-demo";
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("chineseName", "刘志");
        dataMap.put("englishName", "LiuZhi");
        dataMap.put("idNumber", "34122119740702392X");
        dataMap.put("dataOfIssue", "2018-08-11");
        dataMap.put("dateOfExpiry", "2034-08-11");
        dataMap.put("nationality", "CHN");
        dataMap.put("create_time", "2024-12-20");
        Map<String, Object> imageMap = new HashMap<>();
        imageMap.put("img_af_image", basePath + "/20241220105431.png");
        Map<String, Object> formMap = new HashMap<>();
        formMap.put("dataMap", dataMap);
        formMap.put("imageMap", imageMap);
        formMap.put("sex", "F");
        String imgPath = basePath + "/img/AAA";
        String pdfPath = basePath + "/QQF_SQ_1.pdf";
        try {
            fillPDFTemplate(formMap, pdfPath, imgPath);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }
    }

  2)实现代码 

    /**
     * 填充PDF模板并生成图片
     *
     * @param sourceMap  数据源Map
     * @param newPdfPath 新的PDF路径
     */
    public static void fillPDFTemplate(Map<String, Object> sourceMap, String PdfPath, String newPdfPath) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(PdfPath);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        PdfStamper stamper = new PdfStamper(reader, bos);
        AcroFields form = stamper.getAcroFields();
        String sex = sourceMap.get("sex").toString();
        if ("M".equals(sex)) {
            addTextByXY(stamper, 170, 705, 14);
        } else {
            addTextByXY(stamper, 200, 705, 14);
        }
        BaseFont baseFont;
        if (isWindowsSystem()) {
            baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
        } else {
            // 设置 SimSun 字体
            baseFont = BaseFont.createFont("/usr/share/fonts/chinese/SIMSUN.TTC,0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        }
        // 处理文字内容
        Map<String, String> dataMap = (Map<String, String>) sourceMap.get("dataMap");
        for (Map.Entry<String, String> entry : dataMap.entrySet()) {
            String value = formatValue(entry.getValue());
            Font font = new Font(baseFont, 9);
            form.setFieldProperty(entry.getKey(), "textfont", baseFont, null);
            form.setFieldProperty(entry.getKey(), "textsize", (font.getSize()), null);
            form.setField(entry.getKey(), value);
        }
        // 处理图片内容
        Map<String, Object> imageMap = (Map<String, Object>) sourceMap.get("imageMap");
        for (Map.Entry<String, Object> entry : imageMap.entrySet()) {
            String imgpath = entry.getValue().toString();
            if (form.getFieldPositions(entry.getKey()) != null) {
                int pageNo = form.getFieldPositions(entry.getKey()).get(0).page;
                com.itextpdf.text.Rectangle signRect = form.getFieldPositions(entry.getKey()).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                Image image = Image.getInstance(imgpath);
                PdfContentByte under = stamper.getOverContent(pageNo);
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                image.setAbsolutePosition(x, y);
                under.addImage(image);
            }
        }
        stamper.setFormFlattening(true);
        stamper.close();

        // 将填充后的PDF转换为图片
        PDDocument pdDocument = PDDocument.load(new ByteArrayInputStream(bos.toByteArray()));
        PDFRenderer pdfRenderer = new PDFRenderer(pdDocument);
        ImageIO.setUseCache(false);
        BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(0, 300, ImageType.RGB);

        // 创建目标文件夹
        File targetFolder = new File(newPdfPath);
        if (!targetFolder.exists()) {
            targetFolder.mkdirs();
        }
        ImageIO.write(bufferedImage, "jpg", new File(newPdfPath + "/" + "_4.jpg"));
        reader.close();
        bos.close();
        pdDocument.close();
    }

    public static boolean isWindowsSystem() {
        String property = System.getProperty("os.name").toLowerCase();
        return property.contains("windows");
    }
    /**
     * 格式化值为字符串
     *
     * @param value 要格式化的值
     * @return 格式化后的字符串
     */
    private static String formatValue(Object value) {
        if (value instanceof Date) {
            return DATE_FORMAT.format((Date) value);
        }
        return value.toString();
    }
    private static void addTextByXY(PdfStamper stamper, Integer x, Integer y, Integer size) throws DocumentException, IOException {
        PdfContentByte content = stamper.getOverContent(1);
        BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
        content.beginText();
        content.setFontAndSize(base, size);
        content.showTextAligned(Element.ALIGN_CENTER, "√", x, y, 0);
        content.endText();
    }

五、效果展示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值