java使用html模板导出pdf(使用freemarker进行渲染)
·
- 依赖
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- ALWAYS required. -->
<dependency>
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-core</artifactId>
<version>1.0.0</version>
</dependency>
<!-- Required for PDF output. -->
<dependency>
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-pdfbox</artifactId>
<version>1.0.0</version>
</dependency>
- 工具类
package com.shell.common.utils.pdf;
import com.openhtmltopdf.pdfboxout.PdfRendererBuilder;
import org.springframework.util.ResourceUtils;
import java.io.OutputStream;
public class PdfUtil {
/**
*
* @param os
* @param htmlContent
* @throws Exception
*/
public static void buildPdf(OutputStream os, String htmlContent) throws Exception {
PdfRendererBuilder builder = new PdfRendererBuilder();
builder.useFont(ResourceUtils.getFile("classpath:templates/fonts/simsun.ttf"), "simsun");
builder.useFastMode();
builder.withHtmlContent(htmlContent, ResourceUtils.getURL("classpath:templates/img/").toString());
builder.toStream(os);
builder.run();
}
}
- 测试代码
package com.step.pdf.demo.controller;
import com.step.pdf.demo.util.PdfUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.thymeleaf.util.DateUtils;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@RestController
public class DemoController {
@GetMapping("pdf2")
public void test2(HttpServletResponse response, HttpServletRequest request) throws Exception {
OutputStream out = response.getOutputStream();
Writer w =null;
ByteArrayOutputStream outStream = null;
Map<String, Object> variables = new HashMap<>();
variables.put("staffName", "staffName");
variables.put("functions", "functions");
variables.put("assessmentDate", "assessmentDate");
variables.put("roles", "roles");
variables.put("aggregateSource", "aggregateSource");
variables.put("questionList", null);
variables.put("comments", null);
variables.put("score", "score");
variables.put("signature", "signature");
variables.put("paperName","paperName");
variables.put("assessmentTypeName","info.getAssessmentTypeName()");
variables.put("pdfFileName","test");
try {
Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);
// 模板路径
String templatePath = "src/main/resources";
// step2 获取模版路径
cfg.setDirectoryForTemplateLoading(new File(templatePath));
Template freemarkerTemplate = cfg.getTemplate("/template/exam-paper.ftlh");
outStream = new ByteArrayOutputStream();
w = new OutputStreamWriter(outStream, "utf-8");
//不要写成下面: 否则无法关闭fos流,打zip包时存取被拒抛异常
//w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
freemarkerTemplate.process(variables, w);
String htmlContent = outStream.toString("utf-8");
PdfUtil.buildPdf(out,htmlContent);
}catch (Exception e) {
e.printStackTrace();
}
finally {
try {
outStream.close();
out.close();
w.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
- 模板代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
<meta charset="UTF-8" />
<title>${pdfFileName}</title>
<style>
@page {
size: A4;
@top-center {
content: element(header);
}
@bottom-center {
font-family: 'simsun', serif;
}
}
html,
body {
font-family: 'simsun', serif;
font-size: 14px;
}
table {
-fs-table-paginate: paginate;
border-collapse: collapse;
width: 100%;
}
.headingBox {
font-size: 18px;
text-align: center;
font-style: italic;
font-weight: bolder;
}
table,
td,
th {
border: 0px solid #555;
padding: 3px 5px;
}
.box1,
.box2,
.box3 {
padding: 10px 20px;
border-top: 1px solid #999;
}
.trBox {
display: flex;
}
.tdBox {
width: 50%;
display: flex;
}
.titleBox {
display: inline-block;
width: 32%;
font-weight: bold;
}
.contentBox {
width: 68%;
color: cornflowerblue;
}
.titleOverviewBox {
display: inline-block;
width: 64%;
font-weight: bold;
}
.contentOverViewBox {
width: 36%;
color: cornflowerblue;
}
.functionTitleBox,
.commentsTitleBox {
font-style: italic;
font-weight: bolder;
margin: 0 0 0 2%;
}
</style>
<style>
#app {
border: 1px solid #999;
width: 550px;
box-sizing: border-box;
margin: 0px auto;
}
#comm {
height: 100px;
}
#content {
white-space: pre-line;
}
</style>
</head>
<body>
<div id="app">
<h3 class="headingBox">Competence Assessment_${assessmentTypeName}</h3>
<div class="box1">
<table border="0px;" class="baseInfoBox">
<tr class="trBox">
<td class="tdBox"><span class="titleBox">Name:</span><span class="contentBox"
>${staffName}</span></td>
<td class="tdBox"></td>
</tr>
<tr class="trBox">
<td class="tdBox"><span class="titleBox">Function:</span><span class="contentBox"
>${functions}</span></td>
<td class="tdBox"><span class="titleOverviewBox">Date:</span><span class="contentOverViewBox"
>${assessmentDate}</span></td>
</tr>
<tr class="trBox">
<td class="tdBox"><span class="titleBox">Role:</span><span class="contentBox"
>${roles}</span></td>
<td class="tdBox"><span class="titleOverviewBox">Aggregate Source:</span><span
class="contentOverViewBox">${aggregateSource}</span></td>
</tr>
</table>
</div>
<#--<#list questionList as question>
<div class="box1">
<h4 class="functionTitleBox">${question.functionName}:</h4>
<div class="w">
<tbody border="0">
<tr>
<td id="content">${question.questionContent}</td>
</tr>
</tbody>
</div>
</div>
<div class="box1">
<h4 class="commentsTitleBox">Comments:</h4>
<div class="c" height="500px" id="comm">
</div>
<div style="display: flex;">
<div style="padding-left: 18em"><span>Score:          </span>
<span>Signature:</span></div>
</div>
</div>
</#list>-->
</div>
</body>
</html>
更多推荐
所有评论(0)