freemarker模板引擎结合node puppeteer库实现html生成图片

时间:2024-03-12 17:54:46

效果图:

先看效果图,以下是基于freemarker模板渲染数据,puppeteer加载html中的js及最后图片生成:

背景:

目前为止,后台java根据html模板或者一个网页路径生成图片,都不支持flex布局及最新的css3属性,这其中的库、插件包括:html2image、cssbox、core-renderer、wkhtmltox、Flying Saucer、node插件phantom 等等,浏览器标签页打开好几十个了????????????很多插件库已经不记得了。经过粗略测试,对flex布局都不支持!

freemarker模板集成及实现:

因为是测试,所以后台模板页面只写了几个css3属性
1、springboot集成freemarker

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

2、freemarker配置项

# application.yml
spring:
  freemarker:
    cache: false
    # 字符集
    charset: UTF-8
    # 检查模板位置
    check-template-location: true
    # 模板内容类型
    content-type: text/html
    expose-request-attributes: true
    expose-session-attributes: true
    request-context-attribute: request
    # 模板位置
    template-loader-path: classpath:/templates/
    # 必须要加 后缀,要不找不到接口
    suffix: .ftl

3、编写模板 f01.ftl

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>freemarker模板</title>
    <#-- 引入条形码库JsBarcode -->
    <script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.5/dist/JsBarcode.all.min.js"></script>
</head>
<body style="font-size: 20px;">
    <div style="display: flex;
        align-items: flex-start;
        border: 1px solid darkred;
        box-shadow: 1px 2px 1px 5px #cccccc;"
    >
        <div style="display:flex;flex-shrink: 0;width:100px;">渲染文字:</div> <h1>${msg}</h1>
    </div>
    <div style="display: flex;align-items: center;margin: 10px 0px;">
        <div>渲染图片: </div><img style="width: 150px;height: 150px;" src="${img}" />
    </div>
    <#--条形码-->
    <#--<div style="display: flex;align-items: flex-end;">-->
        渲染条形码: <svg id="barcode"></svg>
    <#--</div>-->
</body>
<#--用浏览器访问,可以加载js-->
<script>
    let e = document.getElementById("barcode");
    JsBarcode(e, "Hi world!");
</script>
</html>

4、创建接口

之所以创建一个接口,因为测试的时候我是通过接口方式,返回了一个html页面,在使用 puppeteer 生成图片时,可以指定一个网页或者html代码都可以。

@Slf4j
@Controller
public class Test2 {
    @RequestMapping(value = "/ftest")
    public String test(Model model) {
        model.addAttribute("msg", "freemarker模板引擎结合node puppeteer库实现html生成图片,划重点:【支持flex布局等所有的css3属性!!!】");
        model.addAttribute("img", "https://img1.baidu.com/it/u=3764156347,3722190225&fm=253&fmt=auto&app=138&f=JPEG?w=440&h=419");
        return "f01";
    }
}

5、网页测试

我们先在网页上调用接口测试下,看接口、页面是否正常,以下是网页展示的效果。

node puppeteer库下载、实现最终html转图片:

1、下载puppeteer时,可能会有点慢,取决于网络。

// 我下载的是22.1.0,最新版本下载的时候报错了,可能是node版本问题
// 电脑node版本为19.0.0
npm i puppeteer@22.1.0
// 或
yarn add puppeteer@22.1.0

2、使用puppeteer

 page.evaluate() 方法会执行网页或者html中的js代码,这块很关键!上边我们在模板中引入的条形码生成插件,条形码是需要执行js来生成,所以必须且只能在page.evaluate() 方法中执行html中的js代码。其他的没啥说的,注释写的很清楚。

// index.js
const puppeteer = require('puppeteer');
async function test () {
    // 启动浏览器
    const browser = await puppeteer.launch();
    // 创建一个新页面
    const page = await browser.newPage();
    // 下边设置视口的长宽
    await page.setViewport({
        width: 960,
        height: 760,
        deviceScaleFactor: 1,
    });

    // todo 1 可以加载一段html代码
    // await page.setContent(imgHTML);

    // todo 2 也可以访问一个网址(下边这个网址是本地springboot后台接口,会返回一个html页面)
    await page.goto('http://localhost:8001/ftest');

    // 执行您自己的代码
    await page.evaluate(() => {
        let e = document.getElementById("barcode");
        JsBarcode(e, "Hi world!");
    });

    // 截取网页的屏幕截图
    await page.screenshot({path: "./example.png"});
    // 关闭浏览器
    await browser.close();
}
test()

3、执行index.js,图片生成测试,效果还是比较理想的,flex布局及条形码都会展示出来:

总结:

1、主要是 puppeteer这个库来完成的图片生成,至于html或者网页如何获取,还是要根据业务场景来。

2、puppeteer文档地址如下:

Puppeteer | Puppeteer