springboot+Thymeleaf生成PDF

springboot项目创建以后,pom添加

<!--pdf模板生成-->
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-pdf</artifactId>
            <version>9.0.7</version>
        </dependency>

pdf工具类

package com.ydrx.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolver;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.BaseFont;

public class PDFGenerator {
	private Logger logger = LoggerFactory.getLogger(PDFGenerator.class);
	private AbstractConfigurableTemplateResolver templateResolver;
	private TemplateEngine templateEngine;

	public PDFGenerator(final String templatePrefix, final String templateSuffix) {

		this(templatePrefix, templateSuffix, "HTML5", "UTF-8");
	}

	public PDFGenerator(final String templatePrefix, final String templateSuffix, final String templateMode,
			final String templateEncoding) {

		this(new ClassLoaderTemplateResolver());

		this.templateResolver.setPrefix(templatePrefix);
		this.templateResolver.setSuffix(templateSuffix);
		this.templateResolver.setTemplateMode(templateMode);
		this.templateResolver.setCharacterEncoding(templateEncoding);
	}

	public PDFGenerator(AbstractConfigurableTemplateResolver templateResolver) {
		this.templateResolver = templateResolver;
	}

	public PDFGenerator(TemplateEngine templateEngine) {
		this.templateEngine = templateEngine;
	}

	private TemplateEngine getTemplateEngine() {
		if (templateEngine == null) {
			templateEngine = new TemplateEngine();
			templateEngine.setTemplateResolver(templateResolver);
		}

		return templateEngine;
	}

	/**
	 * 根据模板生成一个PDF
	 *
	 * @param ouputPDF
	 *            Target pdf file.
	 * @param template
	 *            Source template.
	 * @param model
	 *            The data for the template.
	 * @throws FileNotFoundException
	 * @throws DocumentException
	 */
	public void generate(File ouputPDF, String template, Map<String, Object> model)
			throws FileNotFoundException, DocumentException {
		final Context ctx = new Context();
		ctx.setVariables(model);

		final TemplateEngine templateEngine = getTemplateEngine();
		String htmlContent = templateEngine.process(template, ctx);

		ITextRenderer renderer = new ITextRenderer();
		ITextFontResolver fontResolver = renderer.getFontResolver();
		try {
			//避免中文为空设置系统字体
			fontResolver.addFont("C:/Windows/Fonts/SIMHEI.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
			fontResolver.addFont("C:/Windows/Fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.error(e.getMessage(), e);
			e.printStackTrace();
		}

		// 解决图片的相对路径问题
		// renderer.getSharedContext().setBaseURL("file:/C:/Users/Administrator.WIN7-1610080938/Desktop/word2pdf/");

		renderer.setDocumentFromString(htmlContent);
		renderer.layout();
		renderer.createPDF(new FileOutputStream(ouputPDF));
	}

}

如果你发现汉字打印没有添加可能是因为没有引用字体。记得更改Linux和windows不同的位置

html页面好多只能使用table排版

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
    <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
    <!--<link rel="stylesheet" href="../css/bootstrap.min.css"/>-->
    <title>回执单</title>
    <style type="text/css">
        *{
            font-family: SimHei
        }
        .container {
            width: 210mm;
            margin-right: auto;
            margin-left: auto;
        }
        .row{
            margin: 0 auto;
            font-size: 14px;
        }
        @page {
            size: 210mm 297mm;
            margin: 0;
        }
        /*凭证回执*/
        .voucher{
            display: flex;
            padding-bottom: 30px;
            display: -ms-flexbox;
        }
        .voucher-table{
            border:1px dotted #999;
            margin-right: 20mm;
        }
        .voucher-table thead{
            font-size: 24px;
            text-align: center !important;
        }
        .voucher-table tr td{
            border: 1px dotted #999;
            border-top: 0;
            border-left: 0;
            line-height: 25px;
            padding-left: 5px;
            width: 15%;
        }
        .voucher-table .td{
            text-align: center;
        }
        .voucher-table .card{
            width: 80px;
        }
        .voucher-table .tdSign{
            height: 100px;
        }
        .tb-padding{
            padding: 10px;
        }

    </style>
</head>
<body style="font-family: SimHei">
<div class="session" id="session">
    <div class="container" style="text-align: center">
        <h4 style="font-weight: 600;font-size: 20px">回执单</h4>
        <div class="row voucher" id="table">
            <!--<div id="left">-->
            <!--银行打印记录-->
            <!--</div>-->
            <table class="voucher-table"  cellspacing="0" cellpadding="0">
                <tr>
                    <td style="padding-right: 5px;font-size: 16px" rowspan="18">银<br/>行<br/>打<br/>印<br/>记<br/>录</td>
                </tr>
                <tr>
                    <td class="td">交易流水号:</td><td colspan="5" align="left" th:text="${sequence}">151003</td>
                </tr>
                <tr>
                    <td class="td">终端设备号:</td><td th:text="${clientNo}">1222132</td>
                    <td class="td">交易机构号:</td><td th:text="${bankNo}">24</td>
                    <td class="td">开户机构号:</td><td th:text="${bankNo}">24</td>
                </tr>
                <tr>
                    <td class="td">交易日期:</td><td th:text="${#dates.format(new java.util.Date(), 'yyyy-MM-dd')}"></td>
                    <td class="td">授权员编号:</td><td th:text="${userFingerInfo.userCode}"></td>
                    <td class="td">授权员姓名:</td><td th:text="${userFingerInfo.userName}"></td>
                </tr>
                <tr>
                    <td class="td">姓名:</td><td th:text="${personInfo.name}"></td>
                    <td class="td">性别:</td><td th:text="${personInfo.sex}"></td>
                    <td class="td">民族:</td><td th:text="${personInfo.nation}"></td>
                </tr>
                <tr>
                    <td class="td">证件类型:</td><td th:text="身份证"></td>
                    <td class="td">证件号码:</td><td th:text="${personInfo.cardNo}"></td>
                    <td class="td">出生日期:</td><td th:text="${personInfo.born}"></td>
                </tr>
                <tr>
                    <td class="td">住址:</td><td colspan="5" align="left" th:text="${personInfo.cardAddress}"></td>
                </tr>
                <tr>
                    <td class="td">签发机关:</td><td colspan="3" th:text="${personInfo.grantDept}"></td>
                    <td class="td">电话号码:</td><td th:text="${personInfo.sex}"></td>
                </tr>
                <tr>
                    <td class="td">有效期限:</td><td th:text="${personInfo.userLifeEnd}"></td>
                    <td class="td">职业:</td><td th:text="${job}"></td>
                    <td class="td">月收入:</td><td th:text="${monthIncome}"></td>
                </tr>
                <tr>
                    <td class="td">联系住址:</td><td colspan="5" align="left" th:text="${personInfo.cardAddress}"></td>
                </tr>
                <tr>
                    <td class="td">联网核查结果 :</td><td colspan="5" align="left">号码与姓名一致且照片存在</td>
                </tr>
                <tr>
                    <td class="td">业务类型 :</td><td colspan="5" th:text="开卡"></td>
                </tr>
                <tr>
                    <td class="td">账户类型:</td><td></td>
                    <td class="td">卡号:</td><td colspan="3"></td>
                </tr>
                <tr>
                    <td class="td">身份证头像:</td><td class="card" colspan="2"><img style="height: 150px" class="" th:src="${head}" alt="" id="front"/></td>
                    <td class="td" rowspan="2">现场采集照片</td><td rowspan="2" colspan="2"><img th:src="${pic}" alt="" id="photo" style="width: 300px"/></td>
                </tr>
                <tr>
                    <td class="td">联网核查头像:</td><td class="card" colspan="2"><img class="img" style="height: 150px" th:src="${head}" alt="" id="back" /></td>
                </tr>
                <tr>
                    <td colspan="6" align="center" style="font-weight: 600">客户确认</td>
                </tr>
                <tr>
                    <td colspan="2" rowspan="2" class="tb-padding">本人确认以上打印资料准确无误,并与本人提出的申请一致。</td>
                    <td class="td tdSign">客户签字</td><td colspan="3"><img width="300" th:src="${sign}" alt=""/></td>
                </tr>
                <tr>
                    <td colspan="4" th:text="${#dates.format(new java.util.Date(), 'yyyy-MM-dd HH:mm:ss')}">&nbsp;&nbsp;2018年6月15日</td>
                </tr>
            </table>
        </div>
    </div>
</div>
</body>
</html>

如果要打印的最好把@page样式加上

使用

PDFGenerator pdfGenerator = new PDFGenerator("templates/",".html");
Map<String,Object> model = new HashMap<>();
        filePath = Base64Utils.getUrl(filepath,personInfo.getCardNo());
        model.put("front",Base64Utils.ImageToBase64ByLocal(filePath+"front.jpg"));
        model.put("back",Base64Utils.ImageToBase64ByLocal(filePath+"back.jpg"));
        File file = new File(filePath+personInfo.getCardNo()+"_id.pdf");

        try {
//file是要生成的文件名
//中间为modlViewName
//model传到页面的参数
            pdfGenerator.generate(file,"card/voucher3",model);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章