向PDF写入签名日期

前言

需求是要在pdf上进行签字,生成签字日期。签字是使用的第三方信手书工具,但是不会自动生成日期,需要后端在签好字的pdf上将日期填上。


一、导入所需的jar

<dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.11</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>

二、定位日期的位置

定位日期的位置
定位日期位置
读取pdf内容,通过方法processContent传入自定义的监听器CustomRenderListener,然后通过监听器获取关键字的位置信息,因为关键字会在多个位置出现,所以存入pdfKeyWordLocationList中,然后将List里面先通过page页码排序,定位到最后一页,再通过Y轴排序,选出最小值(即最下面位置)

import cn.gtmap.estateplat.olcommon.model.PdfKeyWordLocation;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;

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

/**
 * @ClassName : PdfHelper
 * @Description :
 */
public class PdfHelper {

    /**
     * @Description 用于供外部类调用获取关键字所在PDF文件坐标
     * @param filepath
     * @param keyWords
     * @return float[]
     */
    public static float[] getKeyWordsByPath(String filepath, String keyWords) {
        float[] coordinate = null;
        try{
            PdfReader pdfReader = new PdfReader(filepath);
            coordinate = getKeyWords(pdfReader, keyWords);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return coordinate;
    }

    /**
     * @Description 获取关键字所在PDF坐标
     * @param pdfReader
     * @param keyWords
     * @return float[]
     */
    public static float[] getKeyWords(PdfReader pdfReader, String keyWords) {
        float[] coordinate = new float[3];
        List<PdfKeyWordLocation> pdfKeyWordLocationList = new ArrayList<>();
        int page = 0;
        try{
            int pageNum = pdfReader.getNumberOfPages();
            PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(pdfReader);
            CustomRenderListener renderListener = new CustomRenderListener();
            renderListener.setKeyWord(keyWords);
            for (page = 1; page <= pageNum; page++) {
                renderListener.setPage(page);
                pdfReaderContentParser.processContent(page, renderListener);
                pdfKeyWordLocationList.addAll(renderListener.getPdfKeyWordLocationList());
            }
            Collections.sort(pdfKeyWordLocationList, (o1, o2) -> {
                int num = o2.getPage() - o1.getPage();
                if (num == 0) {
                    return (int) (o1.getY() - o2.getY());
                } else {
                    return num;
                }
            });
            coordinate[0] = pdfKeyWordLocationList.get(0).getX();
            coordinate[1] = pdfKeyWordLocationList.get(0).getY();
            coordinate[2] = pdfKeyWordLocationList.get(0).getPage();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return coordinate;
    }
}

实现RenderListener接口,通过方法renderText去获取关键字位置信息

import cn.gtmap.estateplat.olcommon.model.PdfKeyWordLocation;
import com.itextpdf.awt.geom.Rectangle2D.Float;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName : CustomRenderListener
 * @Description :
 */
public class CustomRenderListener implements RenderListener {

    private List<PdfKeyWordLocation> pdfKeyWordLocationList = new ArrayList<>();

    private float[] pcoordinate = null;

    private String keyWord;

    private int page;

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public float[] getPcoordinate(){
        return pcoordinate;
    }

    public String getKeyWord() {
        return keyWord;
    }

    public void setKeyWord(String keyWord) {
        this.keyWord = keyWord;
    }

    public List<PdfKeyWordLocation> getPdfKeyWordLocationList() {
        return pdfKeyWordLocationList;
    }

    public void setPdfKeyWordLocationList(List<PdfKeyWordLocation> pdfKeyWordLocationList) {
        this.pdfKeyWordLocationList = pdfKeyWordLocationList;
    }

    @Override
    public void beginTextBlock() {}

    @Override
    public void endTextBlock() {}

    @Override
    public void renderImage(ImageRenderInfo arg0) {}

    @Override
    public void renderText(TextRenderInfo textRenderInfo) {
        String text = textRenderInfo.getText();
        if (null != text && text.contains(keyWord)) {
            Float boundingRectange = textRenderInfo.getBaseline().getBoundingRectange();
            PdfKeyWordLocation pdfKeyWordLocation = new PdfKeyWordLocation();
            pdfKeyWordLocation.setX(boundingRectange.x);
            pdfKeyWordLocation.setY(boundingRectange.y);
            pdfKeyWordLocation.setPage(page);
            pdfKeyWordLocationList.add(pdfKeyWordLocation);
        }
    }

}

根据关键字位置计算出日期位置

private void setFontPosition(PdfContentByte over, String type, float[] f) {
        if (StringUtils.equals("hebmmht", type)) {
            //设置字体的输出位置
            over.setTextMatrix(f[0] + 54.5F, f[1] - 85.0F);
            //要输出的text
            over.showText(DateTimeFormatter.ofPattern("yyyy年MM月dd日").format(LocalDate.now()));
        } else if (StringUtils.equals("hebwxblgy", type)) {
            //设置字体的输出位置
            over.setTextMatrix(f[0] + 52.5F, f[1] - 23.1F);
            //要输出的text
            over.showText(DateTimeFormatter.ofPattern("yyyy年MM月dd日").format(LocalDate.now()));
        } else if (StringUtils.equals("hebwxbldd", type)) {
            //设置字体的输出位置
            over.setTextMatrix(f[0] + 52.5F, f[1] - 23.1F);
            //要输出的text
            over.showText(DateTimeFormatter.ofPattern("yyyy年MM月dd日").format(LocalDate.now()));
        } else if (StringUtils.equals("hebsqs", type)) {
            LocalDate localDate = LocalDate.now();
            //设置字体的输出位置
            over.setTextMatrix(f[0], f[1] - 46.2F);
            //要输出的text
            over.showText(DateTimeFormatter.ofPattern("yyyy").format(localDate));
            //设置字体的输出位置
            over.setTextMatrix(f[0] + 60.5F, f[1] - 46.2F);
            //要输出的text
            over.showText(DateTimeFormatter.ofPattern("MM").format(localDate));
            //设置字体的输出位置
            over.setTextMatrix(f[0] + 115.0F, f[1] - 46.2F);
            //要输出的text
            over.showText(DateTimeFormatter.ofPattern("dd").format(localDate));
        }
    }

向pdf中写入日期

private void writePdfDate(String fileName, String userName, String type) {
        PdfReader reader = null;
        try {
            reader = new PdfReader(fileName);
            fileName = fileName.substring(0, fileName.lastIndexOf("_")) + "_" + DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS").format(LocalDateTime.now()) + ".pdf";
            //根据一个pdfreader创建一个pdfStamper.用来生成新的pdf.
            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(fileName));
            //这个字体是itext-asian.jar中自带的 所以不用考虑操作系统环境问题.
            BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); // set font
            //baseFont不支持字体样式设定.但是font字体要求操作系统支持此字体会带来移植问题.
            Font font = new Font(bf,10);
            font.setStyle(Font.BOLD);
            font.getBaseFont();
            float[] f = PdfHelper.getKeyWords(reader, userName);
            int page = (int) f[2];
            //获得pdfstamper在当前页的上层打印内容.也就是说 这些内容会覆盖在原先的pdf内容之上.
            PdfContentByte over = stamper.getOverContent(page);
            //开始写入文本
            over.beginText();
            //设置字体和大小
            over.setFontAndSize(font.getBaseFont(), 10);
            //设置字体颜色
            over.setColorFill(BaseColor.RED);
            //设置文字的位置
            setFontPosition(over, type, f);
            over.endText();
            stamper.close();
        } catch (IOException | DocumentException e) {
            e.printStackTrace();
        }
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值