参考文章:https://www.cnblogs.com/yunfeiyang-88/p/10984740.html
FreeMarker 中文官方参考手册:http://freemarker.foofun.cn/toc.html
依赖:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.11</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.11</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.1.5</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-itext5</artifactId>
<version>9.1.5</version>
</dependency>
HTML模板template.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Title</title>
<style>
body{
/* 中文字体支持 */
font-family:simsun;
}
.red{
color: red;
}
</style>
</head>
<body>
<div class="red">
${msg}
</div>
</body>
</html>
PdfUtil:
@Component
public class JavaToPdfHtmlFreeMarker {
private static FreeMarkerConfigurer freeMarkerConfigurer;
@Autowired
public void setFreeMarkerConfigurer(FreeMarkerConfigurer freeMarkerConfigurer) {
JavaToPdfHtmlFreeMarker.freeMarkerConfigurer = freeMarkerConfigurer;
}
private static final String HTML = "template.html";
private static final String FONT = "templates/simsun.ttf";
public static void createPdf(String content, OutputStream outputStream) {
try {
ITextRenderer renderer = new ITextRenderer();
ITextFontResolver fontResolver = renderer.getFontResolver();
fontResolver.addFont(FONT, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
// 添加多种字体
fontResolver.addFont("templates/方正小标宋.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
renderer.setDocumentFromString(content);
renderer.layout();
renderer.createPDF(outputStream);
} catch (DocumentException | IOException e) {
throw new RuntimeException(e);
}
}
/**
* freemarker渲染html
*/
public static String freeMarkerRender(Map<String, Object> data, String htmlTmp) {
Writer out = new StringWriter();
try {
// 获取模板,并设置编码方式
Template template = freeMarkerConfigurer.getConfiguration().getTemplate(htmlTmp);
template.setEncoding("UTF-8");
// 合并数据模型与模板
template.process(data, out);
out.flush();
return out.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
return null;
}
}
controller层实现:
@PostMapping("/exportPaper")
public void exportPdf(HttpServletResponse response) throws IOException {
Map<String, Object> data = new HashMap<>();
response.setCharacterEncoding("UTF-8");
// 设置强制下载不打开
response.setContentType("application/force-download");
String encode = URLEncoder.encode("pdf", "utf-8");
// 设置文件名
response.addHeader("Content-Disposition", "attachment;fileName=" + encode);
String content = PdfUtil.freeMarkerRender(data, "template.html");
ServletOutputStream outputStream = response.getOutputStream();
PdfUtil.createPdf(content, outputStream);
// 关闭流
outputStream.close();
response.flushBuffer();
}
前端下载:
axios({
url: url,
method: 'post',
responseType: 'arraybuffer'
}).then(res => {
let url = window.URL.createObjectURL(new Blob([res]))
let link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', '文件名.pdf')
document.body.appendChild(link)
link.click()
document.body.removeChild(link) //下载完成移除元素
window.URL.revokeObjectURL(url) //释放掉blob对象
})