1.引入pom
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>kernel</artifactId>
<version>7.1.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>layout</artifactId>
<version>7.1.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>font-asian</artifactId>
<version>7.1.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>html2pdf</artifactId>
<version>3.0.2</version>
</dependency>
2.编写html模板,这里需要注意所有的标签都需要有结束标签,并且需要对模板变量进行空处理,否则会直接抛出异常
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Document</title>
<style>
h2 {
text-align: center;
}
table {
width: 100%;
border-collapse: collapse;
}
td {
padding: 10px;
text-align: center;
border: 1px solid black;
}
.leftTxt td {
border: none;
text-align: left;
}
</style>
</head>
<body>
<h2>采购订单</h2>
<table>
<tr class="leftTxt">
<td colspan="2"><b>供应商:</b>${(mchtName)!''} </td>
<td colspan="2"><b>业务日期:</b>${(applyTime)!''} </td>
<td colspan="2"><b>订单编号:</b>${(applyNo)!''} </td>
</tr>
<tr class="leftTxt">
<td colspan="2"><b>采购员:</b>${(customerName)!''} </td>
<td colspan="4"><b>收货地址:</b>${(receiverAddress)!''} </td>
</tr>
<tr>
<td><b>产品类型</b></td>
<td><b>产品名称</b></td>
<td><b>数量</b></td>
<td><b>计量单位</b></td>
<td><b>含税单价(元)</b></td>
<td><b>含税金额(元)</b></td>
</tr>
<#if productList?? && (productList?size >0)>
<#list productList as product>
<tr>
<td>${(product.deviceModel)!''}</td>
<td>${(product.productName)!''}</td>
<td>${(product.deliverNums)!''}</td>
<td>${(product.unit)!''}</td>
<td>${(product.purchasePrice)!''}</td>
<td>${(product.purchaseTotalPrice)!''}</td>
</tr>
</#list>
</#if>
</table>
</body>
</html>
3.代码实现
1.)Controller代码
import freemarker.template.Template;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
@RestController
public class TestController {
@Autowired
private FreeMarkerConfigurer configurer;
@Value("${nf.dc.pdf.fontPath:/opt/appl/spring-cloud/font}")
private String fontPath;
@GetMapping(value = "/apply_order/v1/get")
public void exportTest(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 准备数据
Map<String, Object> dataMap = new HashMap();
dataMap.put("applyNo", "测试");
dataMap.put("mchtName", "测试");
dataMap.put("applyTime", "测试");
dataMap.put("customerName", "测试");
dataMap.put("receiverAddress", "测试");
List<ExportProductmentProductDto> productList = new ArrayList<>();
ExportProductmentProductDto dto = new ExportProductmentProductDto();
dto.setUnit("台");
dto.setProductName("商品1");
dto.setDeliverNums("10");
dto.setPurchasePrice("200.00");
dto.setDeviceModel("M-550");
dto.setPurchaseTotalPrice("2000.00");
productList.add(dto);
productList.add(dto);
productList.add(dto);
dataMap.put("productList", productList);
Template template = configurer.getConfiguration().getTemplate("productment.ftl");
// 该路径用于本地测试使用
// fontPath = "F://workspace/xxx/target/classes";
ServletOutputStream out;
response.setContentType("application/pdf");
// 设置浏览器以下载的方式处理该文件
response.setHeader("content-disposition", "attachment;filename=document.pdf");
out = response.getOutputStream();
PdfUtil.writeFile(dataMap, template, fontPath, out);
}
2.)导出工具类代码
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.font.FontProvider;
import freemarker.template.Template;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import lombok.extern.slf4j.Slf4j;
/**
* PDF工具类
*/
@Slf4j
public class PdfUtil {
/**
* 创建pdf文件
*/
public static void writeFile(Map<String, Object> paramMap, Template template, String fontPath, ServletOutputStream outPutStream) {
log.info("开始创建pdf");
long start = System.currentTimeMillis();
try {
Writer out = new StringWriter();
// 合并数据模型与模板
template.process(paramMap, out);
out.flush();
out.close();
String html = out.toString();
ConverterProperties props = new ConverterProperties();
FontProvider fontProvider = new FontProvider();
PdfFont ttcFont = PdfFontFactory.createTtcFont(fontPath + "/simsun.ttc", 1,
PdfEncodings.IDENTITY_H, false, true);
fontProvider.addFont(ttcFont.getFontProgram());
props.setFontProvider(fontProvider);
props.setCharset("utf-8");
// 导出到本地
// String fileName = fontPath + "/ABC.jpg";
// File file = new File(fileName);
// createDir(fileName);
// FileOutputStream output = new FileOutputStream(file);
// outPutStream = new ByteArrayOutputStream();
PdfDocument pdf = new PdfDocument(new PdfWriter(outPutStream));
pdf.setDefaultPageSize(PageSize.A4);
Document document = HtmlConverter.convertToDocument(html, pdf, props);
document.getRenderer().close();
document.close();
log.info("写入pdf完成,耗时: {}", System.currentTimeMillis() - start);
} catch (Exception e) {
log.error("writeFile", e);
log.error("写入pdf失败: {}", e.getMessage());
}
}
private static void createDir(String fileName) {
File file = new File(fileName);
if (!file.exists()) {
try {
file.getParentFile().mkdirs();
file.createNewFile();
} catch (IOException e) {
return;
}
}
}
}
3.)使用itext导出时需要自己引入一个字体包,如simsun.ttc,否则会抛出异常
4.结果