java使用itextpdf生成pdf并填充自定义数据

项目中有个需求,对于已有的数据生成对应的发票pdf或者合同pdf,这些pdf具有一些特性,就是pdf有固定的格式,类似于表格,我们只要往表格里面填充数据即可。当然,也会涉及到签章,二维码等需求。

总体思路:
1.得到需要生成的pdf的初始模板,包含格式,只是不含数据
2.使用工具Adobe Acrobat,编辑pdf模板,在对应区域生成文本域,每个域都有自己的name
3.java中使用itextpdf对pdf进行操作,将对应的数据填写入pdf

1.使用Adobe Acrobat操作pdf

(1)首先假设我们有一个发票的pdf模板(局部截图)
java使用itextpdf生成pdf并填充自定义数据_第1张图片
(2)下载Adobe Acrobat工具并编辑pdf
我这边使用的是Adobe Acrobat Pro DC,打开pdf后在工具栏中选择准备表单
java使用itextpdf生成pdf并填充自定义数据_第2张图片
我们可以清除默认生成的文本域,按自己的需求进行右键生成文本域大小,这里我生成了一个gfmc的文本域,在这个文本域属性中在外观中可以设置字体的大小,字体的类型;在选项中可以设置文字左对齐,剧中,右对齐,自动换行等。
java使用itextpdf生成pdf并填充自定义数据_第3张图片

2.使用itextpdf操作pdf

当我们对pdf设置完需要的文本域时候,就要对pdf进行一个数据的填充工作。这里展示的是主要的方法代码,并不是整个流程的逻辑代码。
1.获取PdfReader对象

PdfReader reader = new PdfReader(template);//template是模板pdf文件相对路径

2.获取PdfStamper对象,目的是读取模板pdf,写入新的目标文件

File deskFile = new File(filePath);//filePath是将生成的文件
PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(deskFile));

3.获取模板文件中的文本域,并写入数据到新文件中

AcroFields form = stamp.getAcroFields();
form.setField("gfmc", "这是一个购方名称");

4.自定义字体(按需)
(1)加载字体
其中TARGET_COUR_FONT_PATH为字体文件路径

BaseFont courBf = BaseFont.createFont(TARGET_COUR_FONT_PATH, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

(2)文本域赋值并设置字体
其中chunkStr表示文本内容,size1字体大小,size2行距,property为文本域名称

public static void setFieldAndFont(BaseFont bf, PdfStamper stamp, AcroFields form, String chunkStr, Integer size1, Integer size2, String property) {
        try {
            Font font = new Font(bf, size1,-1,new BaseColor(0,0,0));
            List list = form.getFieldPositions(property);

            int page = list.get(0).page;
            PdfContentByte pdfContentByte = stamp.getOverContent(page);
            ColumnText columnText = new ColumnText(pdfContentByte);
            Rectangle rectangle = list.get(0).position;
            columnText.setSimpleColumn(rectangle);
            Chunk chunk = null;
            chunk = new Chunk(chunkStr);
            Paragraph paragraph = new Paragraph(size2, chunk);
            columnText.addText(paragraph);
            paragraph.setFont(font);
            columnText.addElement(paragraph);
            columnText.go();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

5.添加二维码
这里用到的是com.google.zxing


			com.google.zxing
			core
			3.3.3
		
		
			com.google.zxing
			javase
			3.3.3
		
public static void invoiceEwm(PdfStamper stamp, String content) throws Exception {
        if(content == null || "".equals(content)){
            return;
        }
        BufferedImage image = createQrCodeBufferdImage(content, 70, 70);

        //PdfGState gs = new PdfGState();
        PdfContentByte waterMar = stamp.getOverContent(1);// 在内容上方加水印
        //waterMar = stamp.getUnderContent(1);//在内容下方加水印
        // 设置图片透明度为0.2f
        //gs.setFillOpacity(0.2f);
        // 设置笔触字体不透明度为0.4f
        //gs.setStrokeOpacity(0.4f);
        // 开始水印处理
        waterMar.beginText();
        // 设置透明度
        //waterMar.setGState(gs);
        // 设置水印字体参数及大小
        //waterMar.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED), 60);
        // 设置水印对齐方式 水印内容 X坐标 Y坐标 旋转角度
        //waterMar.showTextAligned(Element.ALIGN_CENTER, "公司内部文件,请注意保密!",  500, 430, 45);
        // 设置水印颜色
        waterMar.setColorFill(BaseColor.GRAY);
        // 创建水印图片
        //com.itextpdf.text.Image itextimage = getImage(image, 99);
        com.itextpdf.text.Image itextimage = com.itextpdf.text.Image.getInstance(image, new Color(128, 128, 128));
        // 水印图片位置
        itextimage.setAbsolutePosition(150, 380);
        // 边框固定3
        //itextimage.scaleToFit(200, 200);
        // 设置旋转弧度
        //image.setRotation(30);// 旋转 弧度
        // 设置旋转角度
        //image.setRotationDegrees(45);// 旋转 角度
        // 设置等比缩放
        itextimage.scalePercent(85);
        // 自定义大小
        //itextimage.scaleAbsolute(100, 100);
        // 附件加上水印图片
        waterMar.addImage(itextimage);
        // 完成水印添加
        waterMar.endText();
        // stroke
        waterMar.stroke();
    }
    /**
     * 生成二维码
     * @author swj
     * @date   2019年6月11日下午4:39:16
     * @param contents 二维码的内容
     * @param width 二维码图片宽度
     * @param height 二维码图片高度
     */
public static BufferedImage createQrCodeBufferdImage(String contents, int width, int height){
        Hashtable hints= new Hashtable();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        hints.put(EncodeHintType.MARGIN, 0);
        BufferedImage image = null;
        try {
            BitMatrix bitMatrix = new MultiFormatWriter().encode(
                    contents, BarcodeFormat.QR_CODE, width, height, hints);
            image = toBufferedImage(bitMatrix);
        } catch (WriterException e) {
            e.printStackTrace();
        }
        return image;
    }

6.添加签章(盖章)
在指定位置添加图片

private static void invoiceDefaultSign(PdfStamper stamper, String filePath, int x, int y) throws Exception {

        Resource resource = new ClassPathResource(filePath);
        byte[] bytes = null;
        bytes = FileUtils.is2ByeteArray(resource.getInputStream());

        // 读图片
        Image image = Image.getInstance(bytes);
        // 获取操作的页面
        PdfContentByte under = stamper.getOverContent(1);
        // 根据域的大小缩放图片
        image.scaleToFit(MAIN_SIGN_WIDTH, MAIN_SIGN_HEIGHT);
        // 添加图片
        image.setAbsolutePosition(x, y);
        under.addImage(image);

    }
/**
	 * 通过InputStream 转Byte数组
	 *
	 * @param is
	 * @return
	 * @throws IOException
	 */
	public static byte[] is2ByeteArray(InputStream is) throws IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		byte[] buff = new byte[100];
		int rc = 0;
		while((rc=is.read(buff, 0, 100))>0) {
			baos.write(buff, 0, rc);
		}

		return baos.toByteArray();
	}

7.关闭流
操作完成后,记得在最后关闭流,很简单,但是很重要

finally {
            if (stamp != null) {
                stamp.close();
            }
            if (reader != null) {
                reader.close();
            }
        }

写在最后

如果对pdf的文本域位置要求比较高的,需要逐步的进行微调,还是比较考验耐心的。涉及到数据的安全,一些效果图我就不上传了。如果生成了多个pdf,需要对pdf进行一个合并的操作,最后可以根据需求,上传至公司fastdfs文件服务器等操作。

你可能感兴趣的:(itextpdf)