一、背景
需要根据不同的参数将freemarker的模板转成不同的图片返回给前端下载。
注意:想要图片不模糊,请调整如下参数
sharedContext.setDotsPerPixel(3);
sharedContext.setDPI(523);
二、效果预览
三、项目
1.maven
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-core</artifactId>
<version>9.1.22</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
<version>2.2.9.RELEASE</version>
</dependency>
2.FreemarkerUtil
package com.asyf.freemarkerdemo.util;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ResourceUtils;
import org.w3c.dom.Document;
import org.xhtmlrenderer.layout.SharedContext;
import org.xhtmlrenderer.swing.Java2DRenderer;
import javax.imageio.ImageIO;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.StringWriter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class FreemarkerUtil {
private static Configuration config = null;
static {
String templatePath = FreemarkerUtil.class.getResource("/").getPath() + "templates";
try {
templatePath = ResourceUtils.getURL("classpath:").getPath() + "templates";
} catch (FileNotFoundException e) {
e.printStackTrace();
}
log.info("ftl路径:" + templatePath);
config = new Configuration(Configuration.VERSION_2_3_20);
config.setDefaultEncoding("UTF-8");
try {
config.setClassForTemplateLoading(FreemarkerUtil.class, "/templates");
} catch (Exception e) {
e.printStackTrace();
log.error(e.toString());
}
}
public static String generate(String template, Map params) throws Exception {
Template tp = config.getTemplate(template);
StringWriter stringWriter = new StringWriter();
String htmlStr;
try {
tp.process(params, stringWriter);
htmlStr = stringWriter.toString();
stringWriter.flush();
} finally {
stringWriter.close();
}
return htmlStr;
}
public static BufferedImage html2Img(String html, int width, int height) throws Exception {
byte[] bytes = html.getBytes();
BufferedImage img;
//转BufferedImage
try (ByteArrayInputStream bin = new ByteArrayInputStream(bytes)) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(bin);
Java2DRenderer renderer = new Java2DRenderer(document, width, height);
SharedContext sharedContext = renderer.getSharedContext();
sharedContext.setDotsPerPixel(3);
sharedContext.setDPI(523);
renderer.setBufferedImageType(4);
Map map = new HashMap<>();//设置参数
map.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
map.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
map.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
map.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
map.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
map.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
map.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
map.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
map.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
renderer.setRenderingHints(map);
img = renderer.getImage();
}
return img;
}
}
3.Controller
@RequestMapping(value = "test", method = RequestMethod.GET)
public void html2ImageIo(HttpServletResponse response) throws Exception {
Map<String, Object> param = new HashMap<>();
param.put("name", "中文参数@123abc");
String html = FreemarkerUtil.generate("test.ftl", param);
BufferedImage bufferedImage = FreemarkerUtil.html2Img(html, 1500, -1);
// 设置为png格式的文件
response.setHeader("content-type", "image/png");
//下载文件需要设置如下header
//response.setHeader("content-type", "application/octet-stream");
//response.setHeader("Content-Disposition", "attachment; filename=test.png");
ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
}
4.freemarker文件
<html>
<head>
<title>Welcome</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<style type="text/css">
body,
html,
div,
p {
font-size: 14px;
margin: 0px;
padding: 0px;
font-family: SimSun;
}
p {
word-wrap: break-word;
word-break: break-all;
}
</style>
</head>
<body>
<h1>freemarker模板</h1>
<h2>freemarker模板</h2>
<h3>freemarker模板</h3>
<h4>freemarker模板</h4>
<h5>freemarker模板</h5>
<span>中文参数:${name}</span>
<p>备注:${remark!'无'}</p>
<img src="http://n.sinaimg.cn/blog/transform/240/w650h390/20210728/99a6-d49c53639da1533f4f6f3968568f1ca1.jpg"/>
</body>
</html>
四、git项目地址
https://gitee.com/373616511/java-demo/tree/master/spring-demo/freemarker-demo