itextpdf 根据pdf表单模板填充生成pdf

itextpdf 根据pdf表单模板填充生成pdf

模板创建

示例:使用adobe acrobat工具创建模板

以excel生成表单模板为例

1、创建表单excel

itextpdf 根据pdf表单模板填充生成pdf_第1张图片

2、新建PDF表单模板

打开pdf工具:文件->创建->创建表单
itextpdf 根据pdf表单模板填充生成pdf_第2张图片
itextpdf 根据pdf表单模板填充生成pdf_第3张图片

选择创建的excel导入

itextpdf 根据pdf表单模板填充生成pdf_第4张图片

编辑导入的表单

导入后左侧为字段名,右侧为表单字段内容,即表单占位,可双击进行编辑
名称即为itext读取时获取到的key
itextpdf 根据pdf表单模板填充生成pdf_第5张图片

依赖jar包

<dependency>
	<groupId>com.itextpdfgroupId>
	<artifactId>itextpdfartifactId>
	<version>5.5.13version>
dependency>
<dependency>
	<groupId>cn.hutoolgroupId>
	<artifactId>hutool-allartifactId>
	<version>5.3.5version>
dependency>

实现代码

表单pdf字段配置信息实体类

import com.itextpdf.text.pdf.BaseFont;
import com.test.utils.pdf.PdfCreateUtil;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.Optional;

@Data
@ApiModel("表单pdf字段配置信息")
public class FormPdfFieldConfig {

    @ApiModelProperty("字体大小,默认14")
    private float fontSize = 14f;

    @ApiModelProperty("字体样式")
    private BaseFont baseFont;

    @ApiModelProperty("单元格内段落行间距,默认1.5倍")
    private float cellLineLeading = 1.5f;

    @ApiModelProperty("图片位置x轴坐标")
    private float xPos = -1f;

    @ApiModelProperty("图片位置y轴坐标")
    private float yPos = -1f;

    @ApiModelProperty("图片宽度")
    private float width = -1f;

    @ApiModelProperty("图片高度")
    private float height = -1f;

    public BaseFont getBaseFont() {
        baseFont = Optional.ofNullable(baseFont).orElse(PdfCreateUtil.getDefaultBaseFont());
        return baseFont;
    }
}

表单pdf参数信息实体类

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.Optional;

@Data
@ApiModel("表单pdf参数信息")
public class FormPdfParamInfo {

    @ApiModelProperty("字段填充类型-自适应文本填充")
    public static final String FIELD_FILL_TYPE_ADAPTIVE = "adaptive";

    @ApiModelProperty("字段填充类型-二维码填充")
    public static final String FIELD_FILL_TYPE_QR_IMAGE = "qrImage";

    @ApiModelProperty("字段key")
    private String fieldKey;

    @ApiModelProperty("字符串字段值")
    private String stringValue;

    @ApiModelProperty("图片内容")
    private String imageContent;

    @ApiModelProperty("字段填充类型")
    private String fieldFillType = FIELD_FILL_TYPE_ADAPTIVE;

    @ApiModelProperty("字段配置信息")
    private FormPdfFieldConfig fieldConfig;

    @ApiModelProperty("字段所在pdf页码,从1开始")
    private int pageNum = 1;

    public FormPdfFieldConfig getFieldConfig() {
        fieldConfig = Optional.ofNullable(fieldConfig).orElse(new FormPdfFieldConfig());
        return fieldConfig;
    }
}

表单类型pdf字段处理工具类

import cn.hutool.extra.qrcode.QrCodeUtil;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.test.constants.NumberConst;
import com.test.vo.pdf.FormPdfFieldConfig;
import com.test.vo.pdf.FormPdfParamInfo;

import java.awt.image.BufferedImage;
import java.io.IOException;

/**
 * 表单类型pdf字段处理工具类
 */
public class PdfFormFieldUtil {

    /**
     * 自适应塞值
     * @param acroFields
     * @param paramInfo
     */
    public static void setAdaptiveField(AcroFields acroFields, PdfContentByte pdfContentByte, FormPdfParamInfo paramInfo) {
        PdfPTable pdfPtable = new PdfPTable(NumberConst.NUM_1);

        Rectangle rectangle = acroFields.getFieldPositions(paramInfo.getFieldKey()).get(NumberConst.NUM_0).position;

        float totalWidth = rectangle.getRight() - rectangle.getLeft() - 1;
        pdfPtable.setTotalWidth(totalWidth);

        getTable(pdfPtable, rectangle, paramInfo);

        pdfPtable.writeSelectedRows(0, -1, rectangle.getLeft(), rectangle.getTop(), pdfContentByte);
    }

	/**
     * 添加二维码/图片(待验证优化)
     * @param acroFields
     * @param pdfContentByte
     * @param paramInfo
     * @throws DocumentException
     * @throws IOException
     */
    public static void setQrImage(AcroFields acroFields, PdfContentByte pdfContentByte, FormPdfParamInfo paramInfo) throws DocumentException, IOException {

        Rectangle rectangle = acroFields.getFieldPositions(paramInfo.getFieldKey()).get(NumberConst.NUM_0).position;
        FormPdfFieldConfig fieldConfig = paramInfo.getFieldConfig();

        BufferedImage bufImg = QrCodeUtil.generate(paramInfo.getImageContent(), 400, 400);
        Image image = Image.getInstance(bufImg, null);

        float x = fieldConfig.getXPos()>0 ? fieldConfig.getXPos() : rectangle.getLeft();
        float y = fieldConfig.getYPos()>0 ? fieldConfig.getYPos() : rectangle.getBottom();
        image.setAbsolutePosition(x, y);

        float width = fieldConfig.getWidth()>0 ? fieldConfig.getWidth() : rectangle.getWidth();
        float height = fieldConfig.getHeight()>0 ? fieldConfig.getHeight() : rectangle.getHeight();
        image.scaleToFit(width, height);

        pdfContentByte.addImage(image);
    }

    /**
     * 关于PDF单元格间距及字体大小自动缩放实现
     * 2019-02-13
     * @param table
     * @param rectangle
     * @param paramInfo
     * @return
     */
    private static void getTable(PdfPTable table, Rectangle rectangle, FormPdfParamInfo paramInfo) {
        FormPdfFieldConfig fieldConfig = paramInfo.getFieldConfig();

        Font cellTitleFont = new Font(fieldConfig.getBaseFont(), fieldConfig.getFontSize(), Font.NORMAL);
        Paragraph titleTitle = new Paragraph(paramInfo.getStringValue(),cellTitleFont);
        PdfPCell cell = new PdfPCell(titleTitle);
        //单元格设置Border
        cell.setBorderWidth(0);
        //单元格内容上边距距离
        cell.setPaddingTop(-5f);
        //单元格内容多行间间距
        cell.setLeading(0f, fieldConfig.getCellLineLeading());
        table.addCell(cell);
        float i = 0.5f;
        float j = 0.1f;
        if(table.getTotalHeight()>rectangle.getHeight()){
            table.deleteBodyRows();
            fieldConfig.setFontSize(fieldConfig.getFontSize()-i);
            fieldConfig.setCellLineLeading(fieldConfig.getCellLineLeading()-j);
            getTable(table, rectangle, paramInfo);
        }
    }

}

pdf生成工具类

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

@Slf4j
public class PdfCreateUtil {

    private static BaseFont DEFAULT_BASE_FONT = null;

    /**
     * 使用表单类型pdf模板填充生成pdf
     * @param paramMap
     * @param fileConfig
     * @return
     */
    public static byte[] createPdfByFormTemplate(Map<String, FormPdfParamInfo> paramMap, PdfFileConfig fileConfig) {
        try {
            String basePath = PdfCreateUtil.class.getClassLoader().getResource("").getFile();
            //获取默认字体
            BaseFont baseFont = BaseFont.createFont(basePath + Optional.ofNullable(fileConfig.getFontFilePath()).orElse("fontfiles/song.ttf"), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            DEFAULT_BASE_FONT = baseFont;

            ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
            fontList.add(baseFont);
            //获取模版
            PdfReader pdfReader = new PdfReader(basePath + fileConfig.getPdfTempPath());
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            PdfStamper pdfStamper = new PdfStamper(pdfReader, outputStream);
            AcroFields acroFields = pdfStamper.getAcroFields();
            //设置模版字体
            acroFields.setSubstitutionFonts(fontList);

            Map<String, AcroFields.Item> fieldMap = acroFields.getFields();
            for (String fieldKey : fieldMap.keySet()) {
                FormPdfParamInfo paramInfo = paramMap.get(fieldKey);

                if (paramInfo != null){
                    switch (paramInfo.getFieldFillType()){
                        case FormPdfParamInfo.FIELD_FILL_TYPE_QR_IMAGE:
                            // 填充二维码/图片
                            PdfFormFieldUtil.setQrImage(acroFields, pdfStamper.getOverContent(paramInfo.getPageNum()), paramInfo);
                            break;
                        default:
                            // 默认自适应填充文本
                            PdfFormFieldUtil.setAdaptiveField(acroFields, pdfStamper.getOverContent(paramInfo.getPageNum()), paramInfo);
                    }
                }
            }

            pdfStamper.setFormFlattening(true);
            pdfStamper.close();
            pdfReader.close();
            outputStream.close();

            return outputStream.toByteArray();

        } catch (Exception e) {
            log.error("pdf生成异常", e);
        }
        return null;
    }

    public static BaseFont getDefaultBaseFont() {
        return DEFAULT_BASE_FONT;
    }
}

使用示例(数据组装)

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.test.constant.BusiConstant;
import com.test.constants.NumberConst;
import com.test.utils.pdf.PdfCreateUtil;
import com.test.vo.pdf.FormPdfParamInfo;
import com.test.vo.pdf.PdfFileConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

public byte[] createPdfByTemplate(String type, JSONObject paramJson) {
        Map<String, FormPdfParamInfo> paramMap = new HashMap<>(NumberConst.NUM_4);
        PdfFileConfig fileConfig = new PdfFileConfig();

        if (StringUtils.isBlank(type)){
            log.error("类型参数为空");
            return null;
        }

        if (OtherbusiConstant.ENTERPRISE_TYPE_ENTERPRISE.equals(type)){
            // 类型1
            fileConfig.setPdfTempPath("pdftemplate/template1.pdf");
        } else if (OtherbusiConstant.ENTERPRISE_TYPE_INDIVIDUAL.equals(type)){
            // 类型2
            fileConfig.setPdfTempPath("pdftemplate/template2.pdf");
        }

        if (paramJson == null || paramJson.isEmpty()){
            log.error("pdf生成参数数据为空,type=", type);
            return null;
        }

        paramJson.entrySet().forEach( entry -> {
            FormPdfParamInfo paramInfo = new FormPdfParamInfo();
            paramInfo.setFieldKey(entry.getKey());
            paramInfo.setStringValue((String) Optional.ofNullable(entry.getValue()).orElse(""));

            if (BusiConstant.TYPE_FIRST.equals(type)){
                if (BusiConstant.TYPE_SECOND.contains(entry.getKey())){
                    paramInfo.setPageNum(NumberConst.NUM_2);
                }
            }

            paramMap.put(entry.getKey(), paramInfo);
        });

        return PdfCreateUtil.createPdfByFormTemplate(paramMap, fileConfig);
    }

你可能感兴趣的:(#,java工具类,pdf,java,itextpdf,pdf表单)