itextpdf对PDF文件进行签名

一、POM引用依赖

<dependency>
      <groupId>com.itextpdf</groupId>
      <artifactId>itextpdf</artifactId>
      <version>5.5.6</version>
  </dependency>
  <!-- itextpdf的亚洲字体支持 -->
  <dependency>
      <groupId>com.itextpdf</groupId>
      <artifactId>itext-asian</artifactId>
      <version>5.2.0</version>
  </dependency>

二、上代码

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.time.LocalDateTime;
import java.util.*;
/**
 * pdf签名工具(图片)
 */
public class PdfSignUtil {
    /**
     * 图片宽度
     */
    private static int imageWith = 120;
    /**
     * 图片高度
     */
    private static int imageHight = 60;


    /**
     * 盖章时间
     * @param pdfBase64 文书pdf
     * @throws IOException
     * @throws DocumentException
     */
    public static String sealSign(String pdfBase64) throws IOException, DocumentException {
        String sealTime = "&D0";
        InputStream input = FileUtils.baseToInputStream(pdfBase64.getBytes());
        PdfReader reader = new PdfReader(input);
        Map<Integer, List<KeyWordBean>> map = getPDFText(pdfBase64);
        File temp = File.createTempFile(System.currentTimeMillis()+new Random(100).nextInt()+"", ".pdf");
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(temp));
        //
        signTime(stamper,map,sealTime);
        stamper.close();
        reader.close();
        return Base64.createBase64().encode(FileUtils.readFileTobytes(temp));
    }


    /**
     * @param pdfBase64 文书pdf
     * @param imagePath 签名图片路径
     * @param index 顺序码 从0开始
     * @throws IOException
     * @throws DocumentException
     */
    public static String sign(String pdfBase64, String imagePath,int index,String signWord,String signWordTime, String signIdea, String authIdea) throws IOException, DocumentException {
        InputStream input = FileUtils.baseToInputStream(pdfBase64.getBytes());
        PdfReader reader = new PdfReader(input);
        Map<Integer, List<KeyWordBean>> map = getPDFText(pdfBase64);
        // 2.获取关键字坐标
        List<KeyWordBean> beanlist = getKeyWordXYLast(map, signWord);
        if(beanlist.isEmpty()){
            return null;
        }
        File temp = File.createTempFile(System.currentTimeMillis()+new Random(100).nextInt()+"", ".pdf");
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(temp));
        AcroFields form = stamper.getAcroFields();
        form.addSubstitutionFont(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false));
        KeyWordBean keyWordBean = beanlist.get(0);
        // 通过域名获取所在页和坐标,右下角为起点
        // 通过域名获取所在页和坐标,左下角为起点
        int pageNo = keyWordBean.getPage();
        float x = keyWordBean.getX();
        // float x = keyWordBean.getX() + keyWordBean.getWidth();
        float y = keyWordBean.getY();
        // 读图片
        Image image = Image.getInstance(imagePath);
        // 获取操作的页面
        PdfContentByte under = stamper.getOverContent(pageNo);
        // 根据域的大小缩放图片
//        image.scaleToFit(imageWith,60 * (index + 1));
        //image.scaleAbsolute(imageWith, imageWith);
        image.scaleAbsolute(keyWordBean.getWidth(), keyWordBean.getWidth() * imageHight / imageWith );
        // 添加图片
        image.setAbsolutePosition(x, y);
        image.setInterpolation(true);
        under.addImage(image);
        //
        if(StringUtils.isNotBlank(signWordTime)){
            signTime(stamper,map,signWordTime);
        }
        //
        if(StringUtils.isNotBlank(signIdea)){
            signIdea(stamper,map,signIdea,authIdea);
        }
        stamper.close();
        reader.close();
        return Base64.createBase64().encode(FileUtils.readFileTobytes(temp));
    }

    public static void signTime(PdfStamper stamper, Map<Integer, List<KeyWordBean>> map,String signWordTime) throws IOException, DocumentException {
        List<KeyWordBean> beanlist = getKeyWordXYLast(map, signWordTime);
        if(beanlist.isEmpty()){
            return;
        }
        for (KeyWordBean keyWordBean : beanlist) {
            // 通过域名获取所在页和坐标,左下角为起点
            int pageNo = keyWordBean.getPage();
            float x = keyWordBean.getX();
            float y = keyWordBean.getY();
            PdfContentByte overContent = stamper.getOverContent(pageNo);
            BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
            overContent.beginText();
            overContent.setFontAndSize(font, 10);
            overContent.setTextMatrix(200, 200);
            overContent.showTextAligned(Element.ALIGN_CENTER,DateUtils.formatDate(LocalDateTime.now(),"yyyy年MM月dd日"),x+34,y,0);
            overContent.endText();
        }
    }

    public static void signIdea(PdfStamper stamper, Map<Integer, List<KeyWordBean>> map,String signIdea, String authIdea) throws IOException, DocumentException {
        List<KeyWordBean> beanlist = getKeyWordXYLast(map, signIdea);
        authIdea = StringUtils.isBlank(authIdea) ? "" : authIdea;
        if(beanlist.isEmpty()){
            return;
        }
        KeyWordBean keyWordBean = beanlist.get(0);
        // 通过域名获取所在页和坐标,左下角为起点
        int pageNo = keyWordBean.getPage();
        float x = keyWordBean.getX();
        float y = keyWordBean.getY();
        PdfContentByte overContent = stamper.getOverContent(pageNo);
        BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
        overContent.beginText();
        overContent.setFontAndSize(font, 10);
        overContent.setTextMatrix(200, 100);
        overContent.showTextAligned(Element.ALIGN_CENTER,authIdea,x+34,y,0);
        overContent.endText();
        return;
    }

    /**
     * 将pdf内容按页面读取map中,map中的key为pdf的页面,value为该页的内容块list
     * @param filePath
     * @return
     */
    public static Map<Integer, List<KeyWordBean>> getPDFText(String filePath) {
        Map<Integer, List<KeyWordBean>> map = new HashMap<Integer, List<KeyWordBean>>();
        try {
            PdfReader pdfReader = new PdfReader(FileUtils.baseToInputStream(filePath.getBytes()));
            int pageNum = pdfReader.getNumberOfPages();
            PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(pdfReader);

            for (int i = 1; i <= pageNum; i++) {
                List<KeyWordBean> lists = Lists.newArrayList();
                List<Integer> pagelist = new ArrayList<Integer>();
                pagelist.add(0, i);
                pdfReaderContentParser.processContent(i, new RenderListener() {
                    @Override
                    public void renderText(TextRenderInfo textRenderInfo) {
                        String text = textRenderInfo.getText(); // 整页内容
                        com.itextpdf.awt.geom.Rectangle2D.Float boundingRectange = textRenderInfo.getBaseline()
                                .getBoundingRectange();
                        KeyWordBean bean = new KeyWordBean();
                        bean.setX(boundingRectange.x);
                        bean.setY(boundingRectange.y);
                        bean.setWidth(boundingRectange.width);
                        bean.setPage(pagelist.get(0));
                        bean.setText(text);
                        lists.add(bean);

                    }

                    @Override
                    public void renderImage(ImageRenderInfo arg0) {
                    }

                    @Override
                    public void endTextBlock() {
                    }

                    @Override
                    public void beginTextBlock() {

                    }
                });
                map.put(i, lists);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 根据第几页第几个关键字查找该关键字的xy坐标
     * @param map2 pdf内容块,以页为key
     * @param page 页
     * @param num 页中的第几个
     * @param keyWord 关键字
     * @return
     */
    private static KeyWordBean getKeyWordXY(Map<Integer, List<KeyWordBean>> map2, int page, int num, String keyWord) {
        List<KeyWordBean> list=getKeyWordXY(map2,keyWord);
        for(KeyWordBean bean:list) {
            if(bean.getPage()==page && bean.getNum()==num) {
                return bean;
            }
        }
        return null;
    }

    /**
     * 根据关键字查找该关键字在pdf中的xy坐标list
     * @param map2 key为pdf的页,value为该的内容块list
     * @param keyWord
     * @return
     */
    public static List<KeyWordBean> getKeyWordXYLast(Map<Integer, List<KeyWordBean>> map2,String keyWord) {
        int keyMatch = 1;
        StringBuilder content = new StringBuilder();
        List<KeyWordBean> keywordlist= new ArrayList<KeyWordBean>();
        for(int page:map2.keySet()) {
            List<KeyWordBean> list=map2.get(page);

            Collections.sort(list);// 正序比较
            for (int i = 0; i < list.size(); i++) {
                KeyWordBean bean = list.get(i);
                String text = bean.getText();
                if (i + 1 != list.size()) {
                    KeyWordBean beanNext = list.get(i + 1);
                    float x = beanNext.getX() - bean.getX();
                    float y = beanNext.getY() - bean.getY();
                    if (y == 0 && x <= 1) {
                    } else {
                        if (StringUtils.contains(content.toString(), keyWord) || StringUtils.contains(text, keyWord)) {
                            bean.setNum(keyMatch++);
                            keywordlist.add(bean);

                        } else if ((!StringUtils.isEmpty(text) && keyWord.startsWith(text)) || content.length() > 0) {
                            content.append(text);
                            if (content.length() >= keyWord.length()) {
                                if (StringUtils.contains(content.toString(), keyWord)) {
                                    bean.setNum(keyMatch++);
                                    keywordlist.add(bean);

                                }
                                content = new StringBuilder();
                            }
                        }
                    }
                } else {
                    if (StringUtils.contains(content.toString(), keyWord) || StringUtils.contains(text, keyWord)) {
                        bean.setNum(keyMatch++);
                        keywordlist.add(bean);
                    } else if ((!StringUtils.isEmpty(text) && keyWord.startsWith(text)) || content.length() > 0) {
                        content.append(text);
                        if (content.length() >= keyWord.length()) {
                            if (StringUtils.contains(content.toString(), keyWord)) {
                                bean.setNum(keyMatch++);
                                keywordlist.add(bean);
                            }
                            content = new StringBuilder();
                        }
                    }
                }
            }
        }
        return keywordlist;
    }

    /**
     * 根据关键字查找该关键字在pdf中的xy坐标list
     * @param map2 key为pdf的页,value为该的内容块list
     * @param keyWord
     * @return
     */
    public static List<KeyWordBean> getKeyWordXY(Map<Integer, List<KeyWordBean>> map2,String keyWord) {
        int keyMatch = 1;
        StringBuilder content = new StringBuilder();
        List<KeyWordBean> keywordlist= new ArrayList<KeyWordBean>();
        for(int page:map2.keySet()) {
            List<KeyWordBean> list=map2.get(page);

            Collections.sort(list);// 正序比较
            for (int i = list.size() - 1; i > 0; i --) {
                KeyWordBean bean = list.get(i);
                String text = bean.getText();
                if (i - 1 >= 0) {
                    KeyWordBean beanNext = list.get(i - 1);
                    float x = bean.getX() - beanNext.getX();
                    float y = bean.getY() - beanNext.getY();
                    if (y == 0 && x <= 1) {
                    } else {
                        if (StringUtils.contains(content.toString(), keyWord) || StringUtils.contains(text, keyWord)) {
                            bean.setNum(keyMatch++);
                            keywordlist.add(bean);

                        } else if ((!StringUtils.isEmpty(text) && keyWord.endsWith(text)) || content.length() > 0) {
                            content.insert(0,text);
                            if (content.length() >= keyWord.length()) {
                                if (StringUtils.contains(content.toString(), keyWord)) {
                                    bean.setNum(keyMatch++);
                                    keywordlist.add(bean);

                                }
                                content = new StringBuilder();
                            }
                        }
                    }
                } else {
                    if (StringUtils.contains(content.toString(), keyWord) || StringUtils.contains(text, keyWord)) {
                        bean.setNum(keyMatch++);
                        keywordlist.add(bean);
                    } else if ((!StringUtils.isEmpty(text) && keyWord.startsWith(text)) || content.length() > 0) {
                        content.append(text);
                        if (content.length() >= keyWord.length()) {
                            if (StringUtils.contains(content.toString(), keyWord)) {
                                bean.setNum(keyMatch++);
                                keywordlist.add(bean);
                            }
                            content = new StringBuilder();
                        }
                    }
                }
            }
        }
        return keywordlist;
    }

    public static void main(String[] args) {
        try {
            sign(Base64.createBase64().encode(FileUtils.readFileTobytes("C:\\Users\\xxx\\Desktop\\test02.pdf")),
                    "C:\\Users\\xxx\\Desktop\\166.png",0,"关键字#1",null,null,null);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值