原理是通过freemarker插入数据到html模版里面,html你就叫前端帮你写好,他不写你就告诉你主管让他叫他写,你只管往预留的位置插入数据就行,然后通过itextpdf会将准备好html文件转成PDF。
### 1、准备依赖
<dependency>
<groupId>com.itextpdfgroupId>
<artifactId>html2pdfartifactId>
<version>4.0.3version>
dependency>
<dependency>
<groupId>org.freemarkergroupId>
<artifactId>freemarkerartifactId>
<version>2.3.30version>
dependency>
### 2、准备html模版
<html>
<head>
<meta charset="UTF-8">
<style>
.main-container {
font-family: SF-UI-Text-Regular;
width: 21cm;
margin: 0 auto;
padding: 20px;
}
.float-left {
float: left;
}
.float-right {
float: right;
}
.padding-left-right {
padding-left: 20px;
padding-right: 20px;
}
.margin-left-right {
margin-left: 20px;
margin-right: 20px;
}
.section {
/*border: 3px dashed #CCC;*/
/*padding: 20px;*/
border-Top: 2px dashed #D3D3D3;
padding-Top: 13px;
margin-bottom: 16px;
margin-Top: 20px;
}
.section-details p {
color: #126089;
/*font-size: 16px;*/
}
.grouper {
overflow: hidden;
}
.grid-50 {
width: 50%;
}
@font-face {
font-family: 'SF-UI-Text-Regular';
src: url("https://s3-ap-southeast-1.amazonaws.com/content.staging.whitecoat.global/PDF/Templates/fonts/SF-UI-Text-Regular.otf");
font-style: normal;
}
h1 {
font-size: 22px;
font-family: 'SF-UI-Text-Regular';
}
.h1-main {
margin-top: 90px;
}
p {
margin: 0 0 10px 0;
font-family: 'SF-UI-Text-Regular';
font-size: 12px;
}
.p-spec {
color: #149a9a;
font-weight: bold;
}
table, th, td {
padding: 5px;
border-collapse: collapse;
}
th, td {
border: 1px solid #D3D3D3;
}
.margin-b-30 {
margin-bottom: 30px;
}
.row:after {
content: "";
display: table;
clear: both;
}
.column-4 {
float: left;
width: 33.33%;
padding: 10px;
}
.column-8 {
float: left;
width: 66.66%;
padding: 10px;
}
* {
box-sizing: border-box;
font-size: 12px;
}
style>
head>
<body>
<div class="main-container">
<div style="background-color: #fff">
<div class="grouper main-header grouper padding-left-right" style="padding-top: 20px">
<div class="margin-b-30 row">
<div class="column-4">
<img style="max-width:90%"
src="https://s3-ap-southeast-1.amazonaws.com/content.staging.whitecoat.global/PDF/Templates/Images/WhiteCoat_Tax_Invoice.png">
div>
<div class="column-4">
WhiteCoat Holdings Pte Ltd. <br/>
Clinic Licence No.: 18M0119/01/182 <br/>
201 Henderson Road #05-11/12 <br/>
Apex @ Henderson <br/>
Singapore 159545 <br/>
div>
<div class="column-4">
GST Reg. No: 201610235E <br/>
T: +65 6909 6909 <br/>
F: +65 6909 6909 <br/>
E: contactus@whitecoat.com.sg <br/>
<a style="text-decoration: none;" href="https://whitecoat.com.sg/">whitecoat.com.sga>
div>
div>
div>
<div class="main-body">
<div class="grouper">
<div class="grouper margin-left-right row" style="border-Top: 1px solid #D3D3D3;padding-top:20px;">
<div class="column-4">
Name: <br/>
${data.name!} <br/><br/>
NRIC/FIN/Passport No: <br/>
${data.idNo!}
div>
<div class="column-8">
Invoice No.: <br/>
${data.invoiceNo!} <br/><br/>
Invoice Date: <br/>
${data.invoiceDateStr!} <br/><br/>
<i>This is a computer generated invoice. No signature is required.i>
div>
div>
<div class="grouper margin-left-right" style="border-Top: 1px solid #D3D3D3;padding-top:20px;">
<table>
<tr>
<th>S/Nth>
<th colspan="2">Descriptionth>
<th style="border:1px solid #D3D3D3;">Amountth>
tr>
<tr>
<td style="width:30px;text-align:center;">1td>
<td style="width:550px; border-right: none">
Medication <br/>
<#list data.medicationList as item>
${item.productName!} <br/>
#list>
<i><br/>Subtotali>
td>
<td style="text-align:right; border-left: none">
Quantity <br/>
<#list data.medicationList as item>
${item.quantity!} <br/>
#list>
<i style="color:#fff"><br/>Subtotali>
td>
<td style="width:200px;text-align:right">
<br/>
<#list data.medicationList as item>
$${item.amount!} <br/>
#list>
<br/><i>${data.subtotal!}i>
td>
tr>
<tr>
<td style="text-align:center;">2td>
<td colspan="2">Administrative chargestd>
<td style="text-align:right">$${data.adminCharge!}td>
tr>
<tr>
<td colspan="3" style="text-align:right; border-bottom: none; border-left: none">
Subtotal(Excluding GST)
td>
<td style="text-align:right">$${data.subtotalExcludingGST!}td>
tr>
<tr>
<td colspan="3"
style="text-align:right; ; border-bottom: none; border-top: none; border-left: none">
GST(${data.tax!}%)
td>
<td style="text-align:right">$${data.GST!}td>
tr>
<tr>
<td colspan="3"
style="text-align:right; border-top: none; border-left: none; border-bottom: none">
Total(Including GST)
td>
<td style="text-align:right">$${data.totalIncludingGST!}td>
tr>
table>
div>
<div class="grouper margin-left-right float-left" style="padding-bottom :20px;padding-top :20px">
<span>
Bank remittance details for payment by Bank Telegraphic <br/>
Transfer in Singapore Dollars to:<br/>
Name of Bank: United Overseas Bank Ltd. Holland Branch<br/>
Account Name: Whitecoat Holdings Pte Ltd.<br/>
Account No: 341-308-316-6<br/>
Bank Code: 7375<br/>
Branch Code: 020<br/>
Bank Swift Code: UOVBSGSG
span>
div>
div>
div>
div>
body>
html>
### 3、下载代码
@ApiOperation(value = "下载pdf")
@GetMapping("downloadPDF/staffPurchase")
public ResponseResult download(String id, HttpServletResponse response) throws Exception {
StaffPurchasePDFVo data = staffPurchaseMapper.getStaffPurchasePDFData(id);
HashMap<String, Object> mapData = Maps.newHashMap();
mapData.put("data", data);
long timeMillis = System.currentTimeMillis();
String templateContent = HtmlUtils.getTemplateContent("Staff_Purchase_Receipt.ftl", mapData);
HtmlUtils.html2Pdf(response, templateContent, timeMillis + "");
return ResponseResult.success();
}
### 4、htmlutils代码
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.layout.font.FontProvider;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Map;
import java.util.Objects;
@Slf4j
public class HtmlUtils {
/**
* @return
* @throws Exception
*/
public static String getTemplateDirectory() {
ClassLoader classLoader = HtmlUtils.class.getClassLoader();
URL resource = classLoader.getResource("templates");
try {
return Objects.requireNonNull(resource).toURI().getPath();
} catch (URISyntaxException e) {
log.error("获取模板文件夹失败,{}", e);
}
return null;
}
/**
* 获取模板内容
*
* @param templateName 模板文件名
* @param paramMap 模板参数
* @return
* @throws Exception
*/
public static String getTemplateContent(String templateName, Map<String, Object> paramMap) throws Exception {
Configuration config = ApplicationContextUtil.getBean(FreeMarkerConfigurer.class).getConfiguration();
config.setDefaultEncoding("UTF-8");
Template template = config.getTemplate(templateName, "UTF-8");
return FreeMarkerTemplateUtils.processTemplateIntoString(template, paramMap);
}
/**
* HTML 转 PDF
*
* @param content html内容
* @param outPath 输出pdf路径
* @return 是否创建成功
*/
public static boolean html2Pdf(String content, String outPath) {
try {
ConverterProperties converterProperties = new ConverterProperties();
converterProperties.setCharset("UTF-8");
FontProvider fontProvider = new FontProvider();
fontProvider.addSystemFonts();
converterProperties.setFontProvider(fontProvider);
HtmlConverter.convertToPdf(content, new FileOutputStream(outPath), converterProperties);
} catch (Exception e) {
log.error("生成模板内容失败,{}", e);
return false;
}
return true;
}
/**
* HTML 转 PDF
*
* @param content html内容
* @return PDF字节数组
*/
public static void html2Pdf(HttpServletResponse response, String content,String filename) throws IOException {
response.setHeader("Content-Type", "application/octet-stream");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Disposition", "attachment;filename="+filename+".pdf");
try (ServletOutputStream outputStream = response.getOutputStream()) {
ConverterProperties converterProperties = new ConverterProperties();
converterProperties.setCharset("UTF-8");
FontProvider fontProvider = new FontProvider();
fontProvider.addSystemFonts();
converterProperties.setFontProvider(fontProvider);
HtmlConverter.convertToPdf(content, outputStream, converterProperties);
} catch (Exception e) {
log.error("生成 PDF 失败,{}", e);
}
}
}
ApplicationContextUtil代码、
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
@Configuration
@AutoConfigureOrder(-1)
public class ApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
public static Object getBeanByName(String beanName) {
if (applicationContext == null) {
return null;
}
return applicationContext.getBean(beanName);
}
public static <T> T getBean(Class<T> type) {
return applicationContext.getBean(type);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextUtil.applicationContext = applicationContext;
}
}
https://developer.aliyun.com/article/942606