最近项目中有需求,需要生成一些打印的pdf数据;经过调研发现使用itext生成的pdf的速度最快。下面讲解一下使用itext5+thymeleaf生成pdf的方法;
首先需要引入itext5相关的包,以及动态生成html的模版引擎thymeleaf
<!--模版引擎-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--html模版pdf生成-->
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-itext5</artifactId>
<version>9.1.5</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.2</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.13.2</version>
</dependency>
动态生成html方法如下
public String generateHtml() {
List<DataEntity> dataEntities = buildData();
Map<String, Object> templateValues = ImmutableMap.<String, Object>builder()
.put("dataList", dataEntities).build();
Context context = new Context();
context.setVariables(templateValues);
String html = templateEngine.process("foobar_pdf.html", context);
return html;
}
生成pdf并存储起来
@Autowired
private SpringTemplateEngine templateEngine;
public void generatePdf() {
String html = generateHtml();
try (OutputStream outputStream = new FileOutputStream(
"/Users/yangfan/tools/wkhtmltox/9999.pdf")) {
ITextRenderer renderer = new ITextRenderer();
ITextFontResolver fontResolver = renderer.getFontResolver();
fontResolver.addFont("/font/AlibabaPuHuiTi-2-55-Regular.ttf", "AlibabaPuHuiTi-Regular",
"Identity-H", false, (String) null);
//html转pdf
renderer.setDocumentFromString(html);
renderer.layout();
renderer.createPDF(outputStream, false);
renderer.finishPDF();
} catch (IOException var6) {
log.error("PdfUtil.generatePdfFromTemplate---生成pdf异常", var6);
} catch (DocumentException var7) {
var7.printStackTrace();
}
}
在项目的resource目录下新建一个html模板,内容如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>pdf-100*100</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"/>
<style type="text/css">
@page {
size: 150mm 100mm;
margin: 0mm;
padding: 0mm;
}
* {
margin: 0;
padding: 0;
font-family: AlibabaPuHuiTi-Regular;
}
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
word-break: break-all;
border-spacing: 0;
}
table td {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.paper {
padding: 4mm;
height: 52.01mm;
width: 92mm;
overflow: hidden;
page-break-after: always;
}
.content {
height: 52mm;
width: 92mm;
overflow: hidden;
}
.head {
height: 8.5mm;
width: 100%;
border-bottom: 0.5mm black solid;
}
.summary {
height: 13mm;
width: 90mm;
padding: 1mm;
}
.banner {
height: 4.5mm;
width: 100%;
background-color: black;
}
.barcode-container {
height: 16mm;
width: 86mm;
padding: 2mm 3mm 0 3mm;
}
.footer {
height: 4.5mm;
line-height: 4.5mm;
width: 100%;
text-align: right;
font-size: 9px;
}
.head .title {
font-weight: bold;
font-size: larger;
height: 8.5mm;
line-height: 8.5mm;
text-align: left;
}
.head .order-part {
font-size: medium;
height: 8.5mm;
line-height: 8.5mm;
text-align: right;
}
.summary .part-tr {
height: 6.5mm;
}
.summary .part-tr td {
font-size: 13px;
}
.summary .tr-title {
height: 6.5mm;
line-height: 6.5mm;
text-align: left;
}
.summary .tr-value {
height: 6.5mm;
line-height: 6.5mm;
text-align: left;
}
.banner .banner-left {
text-align: left;
width: 60%;
padding-left: 1mm;
}
.banner .banner-right {
text-align: right;
padding-right: 1mm;
}
.banner td {
line-height: 4mm;
color: white;
font-size: smaller;
}
.barcode-container .barcode {
height: 13mm;
}
.barcode-container .qrcode {
height: 13mm;
width: 18mm;
text-align: left;
}
.barcode-container .code {
height: 3mm;
width: 68mm;
text-align: center;
font-size: smaller;
vertical-align: top;
}
.barcode-container .barcode img {
height: 13mm;
width: 60mm;
display: block;
border: none;
margin: auto;
}
.barcode-container .qrcode img {
height: 13mm;
width: 13mm;
display: block;
border: none;
}
</style>
</head>
<body>
<div class="paper" th:each="data,boxmarkStat:${dataList}">
<div class="content">
<div class="head">
<table>
<tr>
<td class="title">Inbound</td>
<td class="order-part" th:text="'Box '+${data.part} +' of '+ ${data.total}">1 of 3</td>
</tr>
</table>
</div>
<div class="summary">
<div class="part-tr">
<table>
<tr>
<td width="24%" class="tr-title">Warehouse:</td>
<td width="50%" class="tr-value">
<div class="tr-value" style="display: inline-block;max-width: 18mm;overflow: hidden" th:text="${data.stockName}"></div>
<div class="tr-value" style="display: inline-block;max-width: 36mm;overflow: hidden" th:text="${data.stockCode}"></div>
</td>
<td width="12%" class="tr-title">SKUs:</td>
<td class="tr-value" th:text="${data.sku}">3</td>
</tr>
</table>
</div>
<div class="part-tr">
<table>
<tr>
<td width="14%" class="tr-title">Client:</td>
<td width="60%" class="tr-value" th:text="${data.client}">Xiaomi (1001001)</td>
<td width="12%" class="tr-title">PCS:</td>
<td class="tr-value" th:text="${data.totalNum}">400</td>
</tr>
</table>
</div>
</div>
<div class="banner">
<table>
<tr>
<td class="banner-left" th:text="${data.billNo}">IB46178321OBA</td>
<td class="banner-right" th:text="${data.createTime}">2021-09-26 16:01</td>
</tr>
</table>
</div>
<div class="barcode-container">
<table>
<tr>
<td class="barcode"><img th:src="${data.barcode}"/></td>
<td class="qrcode"><img th:src="${data.qrcode}"/></td>
</tr>
<tr>
<td class="code" th:text="${data.serialNum}">IB46178321OBA</td>
</tr>
</table>
</div>
<div class="footer" th:text="${data.madeInChina}?'MADE IN CHINA':''">MADE IN CHINA</div>
</div>
</div>
</body>
</html>