java生成带签名的PDF并转化图片

需求:根据数据信息生成PDF文档(文档包含文本数据——中文、包含复选框、包含签字图片和表格布局),然后将所生成的PDF文档转化为图片显示。
(注:由于表格的确定性,且长时间不需要修改,故表格原本内容均为固定填写)

1.使用iText生成PDF文件

引入iText依赖

<!-- 引入iText依赖 -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.0.6</version>
</dependency>

使用Document生成PDF文件,普通文字使用Paragraph直接添加,但需要注意汉字无法显示的问题需要使用外部引入的字体文件。
添加表格则需要使用PdfPTable,可以自行封装一个方法。

public static void createPDF(String filePath, formInfoApiModel formInfoApiModel)throws Exception{
    //设置pdf纸张大小
    Document document = new Document(PageSize.A4);
    try {
        //设置字体(/simsun.ttf,引入项目中的字体文件,解决汉字无法显示的问题)
        Font font = new Font(BaseFont.createFont( "/simsun.ttf",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED),18);
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filePath));
        /**
         *  pdf内容
         */
        document.open();
        //标题(整个文件标题)——文字部分
        font = new Font(BaseFont.createFont( "/simsun.ttf",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED),10);
        Chunk Chunk = new Chunk("    抽样单编号: ", font);
        document.add(Chunk);
        //添加编号并生成下划线
        Chunk = new Chunk(formInfoApiModel.getGbTblFormInfo().getFormNumber(),font);
        Chunk.setUnderline(BaseColor.BLACK,0.1f,-2f,-25f,2,2);
        document.add(Chunk);
        //标题——表格部分
        PdfPTable table = createTableTitle(writer,formInfoApiModel);
        document.add(table);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (DocumentException e) {
        e.printStackTrace();
    }   catch (IOException e){
        e.printStackTrace();
    } finally{
        document.close();
    }
}

2.使用PdfPTable和PdfPCell生成数据表格

使用PdfPTable生成数据表格,根据实际生成文件表格形式设计数据表格。使用PdfPCell生成表格的单元格,用于拼接数据表格。

/**
* @Method createTableTitle
* @Author zhanglin
* @Version  1.0
* @Description 生成表格标题部分内容
* @param writer
* @Return com.itextpdf.text.pdf.PdfPTable
* @Exception
* @Date 2019-11-26 8:53
*/
public static PdfPTable createTableTitle(PdfWriter writer,formInfoApiModel formInfoApiModel) throws DocumentException,IOException{
    //formInfoApiModel为项目实际数据类型

    //设定任务字体(解决汉字显示内容)
    Font font = new Font(BaseFont.createFont( "/simsun.ttf",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED),10);
    //设定生成表格的规格
    float widthArray[] = {130,250,80,72,48};
    //createPdfPTable为自行封装方法,见下。
    PdfPTable table = createPdfPTable(5,widthArray);//生成一个两列的表格
        //设置单元格高度常量
    int size = 20;

    //createPdfPCell为自行封装方法,见下。
    //添加提示信息为“任务来源”的单元格
    table.addCell(createPdfPCell(size,"任务来源",font,0,0,1,1,
            false,false,false,false));

    //填充任务来源的实际数据
    table.addCell(createPdfPCell(size,formInfoApiModel.getGbTblFormInfo().getFormMissionsource(),font,0,0,1,1,
            false,false,false,false));

    //添加提示信息为“任务类别”的单元格
    table.addCell(createPdfPCell(size,"任务类别",font,0,0,1,1,false,false,false,false));

    /**
      *  添加附带复选框的任务类别的数据
      */
    //createCheckbox为自行封装方法,见下。
    //checkDictionaryInfo为自行封装方法,见下。
    //监督抽检
    table.addCell(createCheckbox(size,"监督抽查",4,"1",
            checkDictionaryInfo(formInfoApiModel.getGbTblFormInfo().getFormMissiontype(),"监督抽查"),font,0,0,false,true,false,false));

    //风险监测
    table.addCell(createCheckbox(size,"风险监测",4,"1",
            checkDictionaryInfo(formInfoApiModel.getGbTblFormInfo().getFormMissiontype(),"监督抽检"),font,0,0,false,false,false,true));

    //返回填充好的数据表格
    return table;
}

定义createPdfPTable方法,生成表格对象。

/**
* @Method createPdfPTable
* @Author zhanglin
* @Version  1.0
* @Description 生成表格
* @param columnSize
* @param widthArray
* @Return com.itextpdf.text.pdf.PdfPTable
* @Exception
* @Date 2019-11-28 14:31
*/
public static PdfPTable createPdfPTable(int columnSize,float widthArray[])throws DocumentException{
    //根据传输的数字和数组,确定需要生成表格的列数和每列的宽度
    PdfPTable table = new PdfPTable(columnSize);//生成一个多列列的表格
    table.setTotalWidth(widthArray);//设置表格的各列宽度
    table.setLockedWidth(true);//锁定每列的宽度
    //返回生成好的表格对象
    return table;
}

定义createPdfPCell方法,生成表格单元格,填充数据表格。

/**
* @Method createPdfPCell
* @Author zhanglin
* @Version  1.0
* @Description 生成表格元素
* @param cellSize
* @param cellText
* @param font
* @param colSpan
* @param rowSpan
* @param center
* @param middle
* @param top
* @param right
* @param bottom
* @param left
* @Return com.itextpdf.text.pdf.PdfPCell
* @Exception
* @Date 2019-11-28 14:10
*/
public static PdfPCell createPdfPCell(int cellSize,String cellText,Font font,int colSpan,int rowSpan,
int center,int middle,boolean top,boolean right,boolean bottom,boolean left){
    //判断字符串是否为空
    if(cellText == null){
        cellText = "";
    }
    //Phrase设置其显示内容
    PdfPCell pdfPCell = new PdfPCell(new Phrase(cellText,font));
    pdfPCell.setFixedHeight(cellSize);//设置单元格固定高度
    //判断显示信息的水平对齐方式
    if(center == 0){
        pdfPCell.setHorizontalAlignment(Element.ALIGN_LEFT);//水平居左
    }else if(center == 1){
        pdfPCell.setHorizontalAlignment(Element.ALIGN_CENTER);//水平居中
    }else {
        pdfPCell.setHorizontalAlignment(Element.ALIGN_RIGHT);//水平居右
    }
    //判断显示信息的垂直对齐方式
    if(middle == 0){
        pdfPCell.setVerticalAlignment(Element.ALIGN_TOP);//垂直居中
    }else if(middle == 1){
        pdfPCell.setVerticalAlignment(Element.ALIGN_MIDDLE);//水平居中
    }else {
        pdfPCell.setVerticalAlignment(Element.ALIGN_BOTTOM);//水平居右
    }
    //判断单元格的表格宽度
    if(bottom){
        pdfPCell.setBorderWidthBottom(0);
    }
    if(left){
        pdfPCell.setBorderWidthLeft(0);
    }
    pdfPCell.setFixedHeight(cellSize);
    if(top){
        pdfPCell.setBorderWidthTop(0);
    }
    if(right){
        pdfPCell.setBorderWidthRight(0);
    }
    if(colSpan != 0){
        pdfPCell.setColspan(colSpan);
    }
    if(rowSpan != 0){
        pdfPCell.setRowspan(rowSpan);
    }
    return pdfPCell;
}

定义createCheckbox方法,生成表格单元格,填充数据表格。

/**
* @Method createCheckbox
* @Author zhanglin
* @Version  1.0
* @Description 生成带复选框的表格元素
* @param cellSize
* @param cellText
* @param textSize
* @param checkName
* @param isCheck
* @param font
* @param colSpan
* @param rowSpan
* @param top
* @param right
* @param bottom
* @param left
* @Return com.itextpdf.text.pdf.PdfPCell
* @Exception
* @Date 2019-11-27 10:04
*/
public static PdfPCell createCheckbox(int cellSize,String cellText,int textSize,String checkName,boolean isCheck,
Font font,int colSpan,int rowSpan,boolean top,boolean right,boolean bottom,boolean left){
    PdfPCell pdfPCell;
    pdfPCell = new PdfPCell(new Phrase(cellText,font));
    //定义CheckboxCellEvent方法,画出复选框形式
    pdfPCell.setCellEvent(new CheckboxCellEvent(checkName,isCheck,textSize));
    //设置单元格固定高度
    pdfPCell.setFixedHeight(cellSize);
    //设置单元格表格宽度
    if(top){
        pdfPCell.setBorderWidthTop(0);
    }
    if(right){
        pdfPCell.setBorderWidthRight(0);
    }
    if(bottom){
        pdfPCell.setBorderWidthBottom(0);
    }
    if(left){
        pdfPCell.setBorderWidthLeft(0);
    }
    //设置单元格是否需要合并行或者合并列
    if(rowSpan != 0){
        pdfPCell.setRowspan(rowSpan);
    }
    if(colSpan != 0){
        pdfPCell.setColspan(colSpan);
    }
    pdfPCell.setHorizontalAlignment(Element.ALIGN_CENTER);//水平居中
    pdfPCell.setVerticalAlignment(Element.ALIGN_MIDDLE);//垂直居中
    return pdfPCell;
}

定义CheckboxCellEvent方法,自行画出复选框形式。

/**
* @ProjectName: quality
* @Package: com.xwkj.quality.utils
* @ClassName: CheckboxCellEvent
* @Author: zhanglin
* @Description: 生成复选框工具类
* @Date: 2019-11-26 9:20
* @Version: 1.0
*/
public class CheckboxCellEvent implements PdfPCellEvent {

    protected String name;//变量名称
    protected boolean flag ;//是否选中
    protected int size;//名称字符长度(便于定位)
    public CheckboxCellEvent(String name, boolean flag,int size) {
        this.name = name;
        this.flag = flag;
        this.size = size;
    }
    // 根据变量名称、选中状态、字符长度生成定位好的复选框
    public void cellLayout(PdfPCell cell, Rectangle position,PdfContentByte[] canvases) {
        PdfWriter writer = canvases[0].getPdfWriter();
        //判断定位位置
        float x = (position.getLeft() + position.getRight()) / 2;
        float y = (position.getTop() + position.getBottom()) / 2;
        // define the position of a check box that measures 20 by 20
        //画勾
        Rectangle rect;
        rect = new Rectangle(x - 54, y - 6, x + 2, y + 3);
        RadioCheckField checkbox = new RadioCheckField(writer, rect, name, "On");
        checkbox.setCheckType(RadioCheckField.TYPE_CHECK);
        //判断复选框的选中状态
        if(flag){
            //设置为选中状态
            checkbox.setChecked(true);
        }
        else{
            checkbox.setChecked(false);
        }
        //画框
        PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
        canvas.setColorStroke(BaseColor.BLACK);
        canvas.setLineDash(1f);
        canvas.rectangle(x - 30, y - 5, 8,8);
        canvas.stroke();
        try {
            writer.addAnnotation(checkbox.getCheckField());
        } catch (Exception e) {
            throw new ExceptionConverter(e);
        }
    }
}

定义checkDictionaryInfo方法,确定复选框的选中状态。

/**
* @Method checkDictionaryInfo
* @Author zhanglin
* @Version  1.0
* @Description 判断变量字符串中是否包含某一变量
* @param checkByString
* @param checkString
* @Return boolean
* @Exception
* @Date 2019-12-04 13:36
*/
public static boolean checkDictionaryInfo(String checkByString,String checkString){

    //判断所传变量是否为空
    if(checkByString == null){
        checkByString = "";
    }
    //判断所传变量中是否含有表格数据规定的变量,即是否选中
    if(checkByString.contains(checkString)){
        return true;
    }else{
        return false;
    }
}

3.向PdfPCell单元格中插入图片

使用Image根据图片路径获取图片,插入到单元格内。(图片由base64格式变量转换而来,使用
createImageBase64自定义方法)

PdfPCell pdfPCell;
//判断是否生成签字图片
String signCheck = createImageByBase64.createImageBase64(formInfoApiModel.getGbTblFormInfo().getFormSignaturecheck(),
        formInfoApiModel.getGbTblFormInfo().getFormNumber(),"Check");
if(signCheck != null){
    //生成后,插入图片
    Image image = Image.getInstance(signCheck);
    //设置图片显示的比例大小
    image.scalePercent(12f);
    //添加图片
    pdfPCell = new PdfPCell(image);
}else{
    //未生成
    pdfPCell = new PdfPCell();
}

4.使用Base64格式变量转换为图片

定义createImageBase64方法,转换图片。

public static String createImageBase64(String sign,String nameNum,String name) throws Exception {
    //传输项目数据    
    String fileNewName = nameNum + name + ".png";
    //设置存储路径
    String fileAdd = dateUtils.formatDateByFormat(new Date(), "yyyyMMdd");
    String filePath = "d://quaUpload/pdf/" + fileAdd + "/" + nameNum + "/" + fileNewName;
    // 签名数据为空数据为空
    if(sign == null){
        return null;
    }else{
        String signStr = sign.split(",")[1];
        //将签名转换为图片
        BASE64Decoder decoder = new BASE64Decoder();
        OutputStream out = null;
        try {
            out = new FileOutputStream(filePath);
            // Base64解码
            byte[] b = decoder.decodeBuffer(signStr);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {// 调整异常数据
                    b[i] += 256;
                }
            }
            out.write(b);
        }catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            out.flush();
            out.close();
            return filePath;
        }
    }
}

5.将Pdf文件转换为图片

使用pdfbox插件将pdf插件转化为图片,引入依赖

<!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox -->
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.12</version>
</dependency>

定义createImage方法,转换图片。(pdf生成转换图片存在两种方法:1.使用 icepdf 2. 使用pdfbox 实现代码基本一致,但是用icepdf转化图片是,有图形 绘画出的复选框中的对勾会转化失败,但是用pdfbox就可以成功转化。)

public static String createImage(String filePath,String nameNum) throws Exception{
    String picUrl = null;
    File file = new File(filePath);
    try {
        //设置存储路径
        String path = "d://quaUpload/pdf/";
        String fileAdd = dateUtils.formatDateByFormat(new Date(), "yyyyMMdd");
        //文件路径
        String filePathImg = path + "/" + fileAdd + "/" + nameNum + "/" + nameNum + ".png";
        //读取文件路径
        picUrl = "http://xiangwangkeji.imwork.net/upload/pdf/"+ fileAdd + "/" + nameNum + "/" + nameNum + ".png";
        //读取pdf文件
        PDDocument doc = PDDocument.load(file);
        PDFRenderer renderer = new PDFRenderer(doc);
        int pageCount = doc.getNumberOfPages();
        for(int i=0; i<pageCount; i++){
            // 方式1,第二个参数是设置缩放比(即像素)
            // BufferedImage image = renderer.renderImageWithDPI(i, 296);
            // 方式2,第二个参数是设置缩放比(即像素)
            BufferedImage image = renderer.renderImage(i, 1f);  //第二个参数越大生成图片分辨率越高,转换时间也就越长
            ImageIO.write(image, "PNG", new File(filePathImg));
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return picUrl;
}

生成图片
在这里插入图片描述

文档图片

在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值