SpringBoot使用HTML转PDF
参考文章: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对象
})
添加水印
修改一下创建pdf的方法
/**
* 创建PDF
*
* @param content html
* @param outputStream 输出流
*/
public static void createPdf(String content, OutputStream outputStream) {
try (ByteOutputStream byteOutputStream = new ByteOutputStream()) {
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(byteOutputStream);
setWatermark(outputStream, byteOutputStream.getBytes(), WATER_MARK);
} catch (DocumentException | IOException e) {
throw new RuntimeException(e);
}
}
/**
* 添加水印
*
* @param outputStream 输出流
* @param bytes pdf流数组
* @param value 水印内容
*/
public static void setWatermark(OutputStream outputStream, byte[] bytes, String value) {
PdfStamper stamper = null;
try {
PdfReader reader = new PdfReader(bytes);
stamper = new PdfStamper(reader, outputStream);
int total = reader.getNumberOfPages() + 1;
PdfContentByte content;
com.itextpdf.text.pdf.BaseFont base = com.itextpdf.text.pdf.BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", com.itextpdf.text.pdf.BaseFont.EMBEDDED);
PdfGState gs = new PdfGState();
for (int i = 1; i < total; i++) {
// 在内容上方加水印
content = stamper.getUnderContent(i);
gs.setFillOpacity(0.3f);
content.setGState(gs);
content.beginText();
content.setColorFill(BaseColor.LIGHT_GRAY);
content.setFontAndSize(base, 50);
content.setTextMatrix(70, 200);
content.showTextAligned(Element.ALIGN_CENTER, value, 300, 400, 55);
content.endText();
}
} catch (Exception e) {
throw new JeecgBootException("setWatermarkError" + e);
} finally {
try {
if (stamper != null) {
stamper.close();
}
} catch (com.itextpdf.text.DocumentException | IOException e) {
throw new RuntimeException(e);
}
}
}

浙公网安备 33010602011771号