欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java 使用 itextpdf5 利用 pdf 模板生成PDF文件

程序员文章站 2022-06-01 08:30:17
...

做项目时,因直接调用浏览器打印不能完全满足业务需求,因此改为pdf文件导出下载。

iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。
首先如果是maven项目的话需要添加以下依赖,普通项目的话在官网(http://itextpdf.com/)下载对应的jar包加入即可。若是maven项目,添加依赖如下:

添加依赖

<!-- pdf 操作 -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.4.3</version>
        </dependency>
        <!-- 条码生成与二维码生成 -->
        <dependency>
            <groupId>net.sf.barcode4j</groupId>
            <artifactId>barcode4j</artifactId>
            <version>2.1</version>
        </dependency>

操作工具类

工具类一

//                            _ooOoo_
//                           o8888888o
//                           88" . "88
//                           (| -_- |)
//                            O\ = /O
//                        ____/`---'\____
//                      .   ' \\| |// `.
//                       / \\||| : |||// \
//                     / _||||| -:- |||||- \
//                       | | \\\ - /// | |
//                     | \_| ''\---/'' | |
//                      \ .-\__ `-` ___/-. /
//                   ___`. .' /--.--\ `. . __
//                ."" '< `.___\_<|>_/___.' >'"".
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |
//                 \ \ `-. \_ __\ /__ _/ .-` / /
//         ======`-.____`-.___\_____/___.-`____.-'======
//                            `=---='
//
//         .............................................
//                  佛祖镇楼                  BUG辟易
//          佛曰:
//                  写字楼里写字间,写字间里程序员;
//                  程序人员写程序,又拿程序换酒钱。
//                  酒醒只在网上坐,酒醉还来网下眠;
//                  酒醉酒醒日复日,网上网下年复年。
//                  但愿老死电脑间,不愿鞠躬老板前;
//                  奔驰宝马贵者趣,公交自行程序员。
//                  别人笑我忒疯癫,我笑自己命太贱;
//                  不见满街漂亮妹,哪个归得程序员?


package com.hong.webTest.common.util;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description  可实现单个PDF模板重复使用生成同一个PDF文件
 * @Author  guoke
 * @Date 2020-12-02 17:40:00
 * @Version 1.0
 **/
// @Slf4j
public class PdfUtil {

    /**
     * 模板阅读器
     */
    private String templatePath;

    /**
     *
     */
    private List<byte[]> outList;

    /**
     * 基准字体
     */
    private BaseFont bf;

    /**
     * 创建PDF处理对象
     * @param templatePath
     * @param fontPath
     * @return
     */
    @SneakyThrows
    public static PdfUtil create(String templatePath,String fontPath){
        PdfUtil pdf = new PdfUtil();
        // 读取pdf模板
        pdf.templatePath = templatePath;
        pdf.bf = BaseFont.createFont(fontPath , BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        return pdf;
    }

    /**
     * 获取结果
     * @return
     */
    @SneakyThrows
    public ByteArrayOutputStream getOutputStream(){
        if (outList == null) {
            return null;
        }
        Document doc = new Document();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        PdfCopy copy = new PdfCopy(doc, out);
        doc.open();
        for (byte[] array:outList) {
            PdfReader reader = new PdfReader(array);
            for (int i = 1; i <= reader.getNumberOfPages(); i++) {
                PdfImportedPage importPage = copy.getImportedPage(reader,i);
                copy.addPage(importPage);
            }
            reader.close();
        }
        doc.close();
        return out;
    }

    @SneakyThrows
    public void copyPage(Map<String,String> strMap, Map<String,Image> imgMap){
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        PdfReader reader = new PdfReader(templatePath);
        PdfStamper stamper = new PdfStamper(reader, bos);
        AcroFields form = stamper.getAcroFields();

        //文字类的内容处理
        form.addSubstitutionFont(bf);
        strMap.forEach((k,v)->{
            try {
                form.setField(k,v);
            } catch (Exception e) {}
        });

        // 图片类的内容处理
        imgMap.forEach((k,v)->{
            try {
                int pageNo = form.getFieldPositions(k).get(0).page;
                Rectangle signRect = form.getFieldPositions(k).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                //读取图片
                Image image = v;
                //获取图片页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //图片大小自适应
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                //添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
            } catch (Exception e) {}
        });

        // 如果为false,生成的PDF文件可以编辑,如果为true,生成的PDF文件不可以编辑
        stamper.setFormFlattening(true);
        stamper.close();
        reader.close();

        if (outList == null){
            outList = new ArrayList<>(8);
        }
        outList.add(bos.toByteArray());
    }


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


        PdfUtil pdfUtil = PdfUtil.create("static/temp/code.pdf", "static/fonts/simhei.ttf");
        for (int i = 0; i < 10; i++) {
            Map<String,String> map = new HashMap();
            map.put("local","0101013A0"+i);
            map.put("count","第 "+i+" 次");
            map.put("boxNo","201901010407600009"+i);
            map.put("deptCode","01010407"+i);
            map.put("deptName","雁塔支行");
            map.put("actCount",i+"");

            Map<String,Image> map1 = new HashMap();
            map1.put("code",Image.getInstance(BarCodeUtil.getInstanceImage("201901010407600009"+i)));
            pdfUtil.copyPage(map,map1);
        }
        ByteArrayOutputStream outputStream = pdfUtil.getOutputStream();
        FileOutputStream fileOutputStream = new FileOutputStream("G:/Test/code123.pdf");
        fileOutputStream.write(outputStream.toByteArray());
        fileOutputStream.close();
    }*/
}

工具类二

//                            _ooOoo_
//                           o8888888o
//                           88" . "88
//                           (| -_- |)
//                            O\ = /O
//                        ____/`---'\____
//                      .   ' \\| |// `.
//                       / \\||| : |||// \
//                     / _||||| -:- |||||- \
//                       | | \\\ - /// | |
//                     | \_| ''\---/'' | |
//                      \ .-\__ `-` ___/-. /
//                   ___`. .' /--.--\ `. . __
//                ."" '< `.___\_<|>_/___.' >'"".
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |
//                 \ \ `-. \_ __\ /__ _/ .-` / /
//         ======`-.____`-.___\_____/___.-`____.-'======
//                            `=---='
//
//         .............................................
//                  佛祖镇楼                  BUG辟易
//          佛曰:
//                  写字楼里写字间,写字间里程序员;
//                  程序人员写程序,又拿程序换酒钱。
//                  酒醒只在网上坐,酒醉还来网下眠;
//                  酒醉酒醒日复日,网上网下年复年。
//                  但愿老死电脑间,不愿鞠躬老板前;
//                  奔驰宝马贵者趣,公交自行程序员。
//                  别人笑我忒疯癫,我笑自己命太贱;
//                  不见满街漂亮妹,哪个归得程序员?


package com.hong.webTest.common.util;

import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import lombok.SneakyThrows;

import java.io.ByteArrayOutputStream;
import java.util.Map;

/**
 * @Description 单个模板单个生成
 * @Author guoke
 * @Date 2020-12-03 18:13:00
 * @Version 1.0
 **/
public class PdfUtil1 {


    @SneakyThrows
    public static byte[] pdfCreate(String templatePath, String fontPath, Map<String,String> strMap, Map<String,Image> imgMap){
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        PdfReader reader = new PdfReader(templatePath);
        PdfStamper stamper = new PdfStamper(reader, bos);
        AcroFields form = stamper.getAcroFields();

        //文字类的内容处理
        BaseFont bf = BaseFont.createFont(fontPath , BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        form.addSubstitutionFont(bf);
        strMap.forEach((k,v)->{
            try {
                form.setField(k,v);
            } catch (Exception e) {}
        });

        // 图片类的内容处理
        imgMap.forEach((k,v)->{
            try {
                int pageNo = form.getFieldPositions(k).get(0).page;
                Rectangle signRect = form.getFieldPositions(k).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                //读取图片
                Image image = v;
                //获取图片页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //图片大小自适应
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                //添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
            } catch (Exception e) {}
        });

        // 如果为false,生成的PDF文件可以编辑,如果为true,生成的PDF文件不可以编辑
        stamper.setFormFlattening(true);
        stamper.close();
        reader.close();

        Document doc = new Document();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        PdfCopy copy = new PdfCopy(doc, out);
        doc.open();
        PdfReader pdfReader = new PdfReader(bos.toByteArray());
        for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) {
            PdfImportedPage importPage = copy.getImportedPage(pdfReader, i);
            copy.addPage(importPage);
        }
        pdfReader.close();
        doc.close();
        return out.toByteArray();
    }
}

推荐使用第一种工具
本文实现对内存使用量较大,待后期优化

说明: 因itextpdf5 本身不支持中文,若无中文字体包,会导致生成的PDF文件中文字体显示空白,因此必须引入中文支持。

PDF模板制作

模板制作工具Adobe Acrobat X Pro安装

此处自行百度该工具Adobe Acrobat X Pro

模板制作

1.先用word制作原型模板,如:

java 使用 itextpdf5 利用 pdf 模板生成PDF文件
制作好后另存为PDF文件。

2.利用Adobe Acrobat X Pro打开原型PDF,制作PDF模板

依次点击 文件>>创建>>创建表单>>选择本文件>>确认
java 使用 itextpdf5 利用 pdf 模板生成PDF文件
右键增加文本域并设置key值
java 使用 itextpdf5 利用 pdf 模板生成PDF文件
java 使用 itextpdf5 利用 pdf 模板生成PDF文件
保存后,模板制作完成。

制作结果

利用上文工具自己弄,LZ懒得写了。

等LZ有时间了学习学习 itextpdf7,然后再写,这个工具类效率实在是不满意。

相关标签: java itextpdf5