基于xhtmlrenderer+freemarker的HTML转图片方法

html转图片网上有很多方式,不过如果想要是动态html转图片,基本上还是需要依靠

xhtmlrenderer+freemarker

 xhtmlrenderer是基于itext的一套渲染器,核心包主要是文本/图片这些简单的文本渲染工具,衍生的就包括了pdf了,关于渲染成pdf的方法可以看我另一篇文章

引入freemarker与xhtmlrenderer

<dependency>
	<groupId>org.freemarker</groupId>
	<artifactId>freemarker</artifactId>
	<version>2.3.28</version>
</dependency>
<dependency>
	<groupId>org.xhtmlrenderer</groupId>
	<artifactId>flying-saucer-core</artifactId>
	<version>9.1.16</version>
</dependency>

准备html模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
    <style>
        body{
            font-family:SimHei;
        }
        .red{
            color: red;
        }
    </style>
</head>
<body>
<h1>
    许可协议
</h1>
<div class="red">
    被许可方:${company}
</div>
<div class="red">
    许可产品:${product}
</div>
<div class="red">
    产品授权类型:${type}
</div>
<div class="red">
    产品使用许可范围:${scope}
</div>
<div class="red">
    产品授权用户人数:${count}
</div>
<div class="red">
    产品授权有效期:${validity}
</div>
<div class="red">
    许可协议编号:${license}
</div>
</body>
</html>

其中的${}符号中的内容就是我们的可变内容

测试类:

@Test
public void test3() throws IOException {
    private final static String agreementDir = "D:/java/agreement/"; //导出位置
	Path basePath = Paths.get(agreementDir);
	if (!Files.exists(basePath) || !Files.isDirectory(basePath)) {
		Files.createDirectory(basePath);
	}

	Map<String, Object> paramMap = new HashMap<>();
	paramMap.put("company", "公司");
    paramMap.put("product", "产品名称");
	paramMap.put("type", "许可证授权");
	paramMap.put("scope", "使用范围");
	paramMap.put("count", "购买数量");
	paramMap.put("validity", "有效期");
	paramMap.put("license", "购买序列码");
	paramMap.put("createTime", DateFormatUtils.format(new Date(), "yyyy年MM月dd日"));

	String freemarker = FileUtils.CURRENT_DIR + File.separator + "freemarker";
    File dir = new File(freemarker);
    String html = PDFUtils.freeMarkerRender(paramMap, "license.html", dir);

    long l = System.currentTimeMillis();

    PDFUtils.createImage(html, agreementDir + l + ".jpg", 480, 640);
}

工具类:

import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Document;
import org.xhtmlrenderer.swing.Java2DRenderer;
import org.xhtmlrenderer.util.FSImageWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;

@Slf4j
public class PDFUtils {

    private static Configuration freemarkerCfg;

    static {
        freemarkerCfg =new Configuration();
    }

    public static String freeMarkerRender(Map<String, Object> data, String htmlTmp, File dir) throws IOException {
        freemarkerCfg.setDirectoryForTemplateLoading(dir);

        Writer out = new StringWriter();
        try {
            Template template = freemarkerCfg.getTemplate(htmlTmp, "utf-8");
            template.process(data, out);
            out.flush();
            return out.toString();
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            try {
                out.close();
            } catch (IOException ex) {
                log.error(ex.getMessage());
            }
        }
        return null;
    }

    /**
     * @Description 图片生成工具
     * @Date 15:52 2020/10/28
     * @Param html 需要生成的模板字符串
     * @Param outputFilename 输入文件地址
     * @Param widthImage 所需图片宽度
     * @Param heightImage 所需图片高度
     * @return void
     **/
    public static void createImage(String html, String outputFilename,
                                   int widthImage, int heightImage) throws Exception {

        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document document = builder.parse(new ByteArrayInputStream(html.getBytes()));

        Java2DRenderer renderer = new Java2DRenderer(document, widthImage, heightImage);

        BufferedImage img = renderer.getImage();
        FSImageWriter imageWriter = new FSImageWriter();
        imageWriter.write(img, outputFilename);
    }
}

这样就可以使用html来生成动态图片了,不过这个工具包对字体图片等的支持度较弱,如果需要的话可以要使用其他的衍生包才能方便一点

关于文件相互转换的方法实际上支持的工具类并不是很多,而且也都只能完成一些简单的需求,如果想要大量的调用而公司内又没有相应的能力,我觉得可以考虑专业的产品了

文档在线预览_文档在线编辑_文档格式转换_永中云服务平台

注册申请可以赠送云端服务,比如:

在线预览(可以直接把pdf/word/excel/ppt等全部转为html5来进行浏览器预览)

在线转换(pdf转word/word转pdf之类的)

在线编辑(可以在线编辑word/excel/ppt等)

功能还是很强大的,而且还可以根据需要在调用api时传递参数实现相应功能,比如预览水印,链接过期,历史版本查看等

上一篇:SpringBoot整合RabbitMQ之Fanout扇形交换器


下一篇:【SpringBoot2—Bean生命周期管理】