一枚有理想的女程序员:java根据模板动态生成pdf文档(springboot+itext )

java根据模板动态生成pdf文档 (springboot+itext )

1.需求说明

根据业务需要,需要在服务器端生成可动态配置的PDF文档,方便数据可视化查看。

2.前期环境准备

1.Adobe Acrobat DC
链接:https://pan.baidu.com/s/1dYBZb8b75D3BbKDN-lJFPA
提取码:yhju
在这里插入图片描述
2.pom文件依赖

   <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itextpdf</artifactId>
                <version>5.5.9</version>
                <scope>compile</scope>
  </dependency>

3.PDFUtils工具类


package com.shine.common.utils;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
 * @author
 * Date on 2020/8/10  8:49
 */
public class PDFUtils {
    private static final Logger log = LoggerFactory.getLogger(PDFUtils.class);

    /**
     * 根据pdf模板输出流
     * @param templateFilePath 模板目录路径
     * @param templateFileName 模板文件名
     * @param resultMap 包含文件字段名和值的map
     * @return 生成的文件字节流
     */
    public static ByteArrayOutputStream createPdfStream(String templateFilePath, String templateFileName,
                                                        Map<String, String> resultMap){

        ByteArrayOutputStream ba = new ByteArrayOutputStream();
        PdfStamper stamp =null;
        PdfReader reader = null;
        try {

            log.debug("file:"+templateFilePath + "/" + templateFileName);
            reader = new PdfReader(templateFilePath + "/" + templateFileName);
            stamp = new PdfStamper(reader, ba);

            //使用字体
            BaseFont bf = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            /* 获取模版中的字段 */
            AcroFields form = stamp.getAcroFields();

            //填充表单
            if (resultMap != null) {
                for (Map.Entry<String, String> entry : resultMap.entrySet()) {

                    form.setFieldProperty(entry.getKey(), "textfont", bf, null);
                    form.setField(entry.getKey(), entry.getValue()!=null?entry.getValue():"");
                }
            }
            //不能编辑
            stamp.setFormFlattening(true);

        } catch (IOException e) {
            log.error("文档构建I/O异常",e);
        } catch (DocumentException e) {
            log.error("文档构建异常",e);
        }
        finally {
            if(stamp!=null){
                try {
                    stamp.close();
                } catch (DocumentException e) {
                    log.error("流关闭错误",e);
                } catch (IOException e) {
                    log.error("流关闭错误",e);
                }
            }
            if(reader!=null){
                reader.close();
            }
        }
        return ba;
    }
}

3.上代码

1.准备模板

使用上面提到的工具将需要生成的word、或者excel生成pdf模板
具体操作:1.双击打开Adobe Acrobat DC工具
2.点击“”工具“”,点击右侧“”准备表单“”选项,然后选择一个文件打开pdf文档
3.修改里面的页面上的文本属性(具体如下图片),鼠标点击右键可修改属性
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注:整个文档的定义的文本属性不可重复(后面填充数据需要用到),不然数据会被后面的覆盖
记得把生成的模板放入项目中 ,项目能找到的路径中(相对路径或绝对路径都可以)

2.获取数据并填充模板

controller类

package com.shine.web.controller.subsystem;

import com.spire.pdf.PdfDocument;
import com.shine.common.utils.DateUtils;
import com.shine.common.utils.PDFUtils;
import com.shine.framework.bean.ResponseResult;
import com.shine.subsystem.domain.*;
import com.shine.subsystem.service.*;
import com.shine.system.service.ISysUserService;
import com.spire.pdf.PdfPageBase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.awt.geom.Rectangle2D;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.util.*;
import java.util.List;

    @GetMapping("/pdf")
    @ResponseBody
    public ResponseResult CreatePdf(String userIdFk) throws Exception {
        Map<String, String> map = new HashMap(130);
        ByteArrayOutputStream pdf = null;

		//获取后台数据库数据放入map中(key,value形式)key是模板中命名的文本属性
        fileMap(map, userIdFk);

        FileOutputStream out = null;
        String newPath=null;
        try {
            //重命名pdf
            newPath = userIdFk + ".reviewForm." + UUID.randomUUID().toString() + ".pdf";
            //新的文件路径  uploadPath是项目的配置文件命名路径  可以自定义  也可生成到本地磁盘中(最后生成的pdf文档路径)
            String newFilePath = uploadPath + "/" + "appraisePath" + "/" + newPath;
            //填充模板   这里是pdf模板的位置
            pdf = PDFUtils.createPdfStream("/upload/templates", "reviewForm_water.pdf", map);



            out = new FileOutputStream(newFilePath);
            out.write(pdf.toByteArray());
//            pteDeclare.setPdf1("pdf"+ File.separator + newPath);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (pdf != null) {
                try {
                    pdf.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.flush();
                    out.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        //返回前台路径
        return ResponseResult.ok().render((Object) newPath);
    }


   private Map<String, String> fileMap(Map<String, String> map, String userIdFk) throws Exception {
        List<PteInformation> pteInformations = pteInformationService.selectAll(userIdFk);
        List<PteQual> pteQuals = pteQualService.selectAll(userIdFk);
        List<PteTest> pteTests = pteTestService.selectAll(userIdFk);
        if (pteInformations.size() > 0 && pteInformations != null) {
            PteInformation pteInformation = pteInformations.get(0);
            //姓名
            map.put("infos_name", pteInformation.getName());
            //工作单位
            map.put("infos_work", pteInformation.getWork());
            //现任专业技术职务
            map.put("infos_postTitle", pteQuals.get(0).getPostTitle());
            //评审任职资格
            map.put("infos_qualifications", "哈哈哈");
            //填表时间
            map.put("infos_createTime", DateUtils.dateTime(DateUtils.getNowDate()));


            /**
             * 基本情况
             */
            //现名
            map.put("info_name", pteInformation.getName());
            //性别
            map.put("info_sex", checkSex(pteInformation.getSex()));
            //民族
            map.put("info_national", pteInformation.getNational());
            //曾用名
            map.put("info_cname", pteInformation.getCname());
            //出生年月
            map.put("info_birthday", DateUtils.dateTime(pteInformation.getBirthday()));
            //政治面貌
            map.put("info_landscape", checkLandscape(pteInformation.getLandscape()));
            //户籍所在地
            map.put("info_residence", pteInformation.getResidence());
        }
 
        return map;
    }

3.生成结果

在这里插入图片描述

也可通过前台预览 根据接口返回的路径,具体就不详细说啦
谢谢观看!!

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值