java pdf增加签名文件 pdf增加图片 ireport模板文件pdf增加图片

需求来源  需要在文件上用输入仪签字/需要pdf上添加图片

注:输入仪签字返回的是 base64格式的图片

流程:

1.通过使用 itextpdf

2.结合 TestRenderListener 获取pdf里的文字坐标 ,增加偏移量,并控制图片大小,使签名图片落在合适位置,保存文件

 

 

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.4.3</version>
</dependency>
<dependency>
    <groupId>org.jodd</groupId>
    <artifactId>jodd-core</artifactId>
    <version>5.1.4</version>
</dependency>

 

注:jodd使用来处理base64 图片的

 

 

代码示例:

package com.mickyss.pdf;

import com.itextpdf.awt.geom.Rectangle2D;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author mickyss
 * @description
 * @since 2020/10/30 0030
 */
public class PDFTest {


    //
    public static void main(String[] args) throws IOException {

        File file = new File("D:\\sign.pdf");
        if(file.exists()){
            System.out.println("123");
        }
        String signBase64 = "这里放base64图片字符串,注意不需要data:image/jpg;base64,这串前缀";
        // 读取模板文件
        InputStream input = new FileInputStream(file);
        PdfReader reader = new PdfReader(input);
        PdfStamper stamper = null;
        //获取受理签名坐标
        List<Map> rectText = new ArrayList();
        try {
            stamper = new PdfStamper(reader, new FileOutputStream(
                    file.getPath()));
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        try {
            //新建一个PDF解析对象
            PdfReaderContentParser parser = new PdfReaderContentParser(reader);
            for(int i = 1;i <= reader.getNumberOfPages();i++) {
                //新建一个ImageRenderListener对象,该对象实现了RenderListener接口,作为处理PDF的主要类
                TestRenderListener listener = new TestRenderListener();
                //解析PDF,并处理里面的文字
                parser.processContent(i, listener);
                List<Map<String, Rectangle2D.Float>> list_text = listener.rows_text_rect;
                for (int k = 0; k < list_text.size(); k++) {
                    Map<String, Rectangle2D.Float> map = list_text.get(k);
                    for (Map.Entry<String, Rectangle2D.Float> entry : map.entrySet()) {
                          //根据text信息 获取文字相对于地址,一般来说签名应该是合在一起的,如果用模板文件如果ireport生成的pdf 则text这里的数据都会是完整的而不是单个字体一个
                        if(entry.getKey().contains("名")){
                            Map mapEntry = new HashMap();
                            mapEntry.put("x",entry.getValue().x);
                            mapEntry.put("y",entry.getValue().y);
                            rectText.add(mapEntry);
                        }
                    }
                }
            }
            for(int i = 0; i<rectText.size();i++ ){
                // 读图片
                Image image = Image.getInstance(Base64Util.decodeToByte(signBase64));
                // 根据域的大小缩放图片
                image.scaleToFit(100,100);
                // 添加图片 这里可以自己加入偏移量
                image.setAbsolutePosition(Float.parseFloat(rectText.get(i).get("x").toString()), Float.parseFloat(rectText.get(i).get("y").toString()));
                PdfContentByte under = stamper.getOverContent(i+1);
                under.addImage(image);
            }
            try {
                stamper.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            reader.close();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}
TestRenderListener 工具类
package com.mickyss.pdf;

import com.itextpdf.awt.geom.Rectangle2D;
import com.itextpdf.awt.geom.RectangularShape;
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.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author mickyss
 * @description
 * @since 2020/10/27 0027
 */
public class TestRenderListener implements RenderListener {

    //用来存放文字的矩形
    List<Rectangle2D.Float> rectText = new ArrayList<Rectangle2D.Float>();
    //用来存放文字
    List<String> textList = new ArrayList<String>();
    //用来存放文字的y坐标
    List<Float> listY = new ArrayList<Float>();
    //用来存放每一行文字的坐标位置
    List<Map<String,Rectangle2D.Float>> rows_text_rect = new ArrayList();
    //PDF文件的路径
    protected String filepath = null;
    public TestRenderListener() {
    }

    //step 2,遇到"BT"执行
    @Override
    public void beginTextBlock() {
        // TODO Auto-generated method stub
    }

    //step 3
    /**
     * 文字主要处理方法
     */
    @Override
    public void renderText(TextRenderInfo renderInfo) {
        //获取文字的下面的矩形
        //Rectangle2D.Float rectBase = renderInfo.getBaseline().getBoundingRectange();
        String text = renderInfo.getText();
        if(text.length() > 0){
            RectangularShape rectBase = renderInfo.getBaseline().getBoundingRectange();
            //获取文字下面的矩形
            Rectangle2D.Float rectAscen = renderInfo.getAscentLine().getBoundingRectange();
            //计算出文字的边框矩形
            float leftX = (float) rectBase.getMinX();
            float leftY = (float) rectBase.getMinY()-1;
            float rightX = (float) rectAscen.getMaxX();
            float rightY = (float) rectAscen.getMaxY()+1;
            Rectangle2D.Float rect = new Rectangle2D.Float(leftX, leftY, rightX - leftX, rightY - leftY);
            if(listY.contains(rect.y)){
                int index = listY.indexOf(rect.y);
                float tempx = rect.x > rectText.get(index).x ? rectText.get(index).x : rect.x;
                rectText.set(index,new Rectangle2D.Float(tempx,rect.y,rect.width + rectText.get(index).width,rect.height));
                textList.set(index,textList.get(index) + text);
            }else{
                rectText.add(rect);
                textList.add(text);
                listY.add(rect.y);
            }
            Map<String,Rectangle2D.Float> map = new HashMap();
            map.put(text,rect);
            rows_text_rect.add(map);
        }
    }
    //step 4(最后执行的,只执行一次),遇到“ET”执行
    @Override
    public void endTextBlock() {
        // TODO Auto-generated method stub
    }

    //step 1(图片处理方法)
    @Override
    public void renderImage(ImageRenderInfo renderInfo) {

    }

}
Base64Util工具类
package com.mickyss.pdf;

import jodd.util.Base64;

/**
 * <p>
 *    类说明:base64编码、解码工具类
 * </p>
 * 
 */
public class Base64Util {


	/**
	 * 对base64编码的字符串进行解码,返回字节数据
	 * 
	 * @param str
	 * @return
	 */
	static public byte[] decodeToByte(String str) {
		return Base64.decode(str);
	}


}

参考: https://blog.csdn.net/sinat_29957455/article/details/78759654?utm_source=blogxgwz14

仓库地址: https://github.com/mickyss/pdf-sign

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值