java 将html页面转成图片

需求:后台代码批量生成图片,图片中的title和二维码,需要动态变化。

 解决思路:
1.使用FreeMaker模板index.ftl渲染动态数据(title和二维码链接作为动态入参)
2.添加动态数据的模板代码通过xhtmlrenderer转换成图片
3.上传图片至图片服务器,获取图片url

拆分实现步骤:
1.使用FreeMaker模板index.ftl渲染动态数据(title和二维码链接作为动态入参)
1.1 引入FreeMaker依赖

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

1.2 准备模板代码 index.ftl

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta http-equiv="Content-Type" content="text/html" charset="UTF-8"></meta>
    <title>海报</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .certificate {
            position: relative;
            display: inline-block;
            width: 750px;
            height: 1288px;
            background-repeat: no-repeat;
            background-position: center;
            background-size: 750px 1288px;
            text-align: center;
        }

        .title {
            position: absolute;
            display: inline-block;
            width: 578px;
            margin: 0 86px;
            font-size: 34px;
            font-weight: 500;
            color: #E66C6C;
            font-family: simsun;
            line-height: 48px;
            top: 410px;
            padding-bottom: 14px;
            border-bottom: 2px solid #E66C6C;
            text-align: center;
        }

        .qr_code {
            position: absolute;
            width: 228px;
            height: 228px;
            background-color: #fff;
            top: 964px;
            left: 260px;


        }

        img {
            display: inline-block;
            width: 228px;
            height: 228px;
        }
    </style>
</head>
<body>
<div class="certificate" style="background-image: url(${bg})">
    <div class="title" style="word-break: break-all!important; word-wrap: break-word!important;">
        《${title?html}》
    </div>
    <div class="qr_code">
        <img src="${qrCode}" alt=""></img>
    </div>
</div>
</body>
</html>

 1.3  FreemarkerUtils加载index.ftl模板,渲染数据

public class FreemarkerUtils {

    public static String getTemplate(String template, Map<String, Object> map) throws IOException, TemplateException {
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_25);
        cfg.setTemplateLoader(new ClassTemplateLoader(
                FreemarkerUtils.class.getClass().getClassLoader(), "/templates/static"));
        cfg.setDefaultEncoding("UTF-8");
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        cfg.setLogTemplateExceptions(false);
        Template temp = cfg.getTemplate(template, "UTF-8");
        StringWriter stringWriter = new StringWriter();
        temp.process(map, stringWriter);
        stringWriter.flush();
        stringWriter.close();
        String resutl = stringWriter.getBuffer().toString();
        return resutl;
    }

}

2.添加动态数据的模板代码通过xhtmlrenderer转换成图片
2.1 引入xhtmlrenderer依赖

<dependency>
  <groupId>org.xhtmlrenderer</groupId>
  <artifactId>core-renderer</artifactId>
  <version>R8</version>
</dependency>

注意xhtmlrenderer中央仓库为:
<repository>
  <id>mvnrepository</id>
  <name>mvnrepository</name>
  <url>https://mvnrepository.com</url>
</repository>

2.2 xhtmlrenderer生成图片

public String turnImage(String template, Map<String, Object> map) throws Exception {

        String html = FreemarkerUtils.getTemplate(template, map);
        byte[] bytes = html.getBytes("UTF-8");

        ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(bin);

        //加载自定义字体,解决生成图片title处汉字展示不正常问题
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("font/simsun.ttf");
        Font font = Font.createFont(TRUETYPE_FONT, inputStream);
        AWTFontResolver awtFontResolver = new AWTFontResolver();
        awtFontResolver.setFontMapping("simsun", font);

        Java2DRenderer renderer = new Java2DRenderer(document, 750, 1286);
        renderer.getSharedContext().setFontResolver(awtFontResolver);

        BufferedImage img = renderer.getImage();
        // 转成流上传至服务器
        ByteArrayOutputStream dataOutputStream = new ByteArrayOutputStream();
        ImageIO.write(img, "png", dataOutputStream);
        byte[] bts = dataOutputStream.toByteArray();
        String imgUrl = uploadPic(bts);
        return imgUrl;
    }

2.3 加载自定义字体,解决生成图片title处汉字展示不正常问题
由于Java2DRenderer类中定义的字体对于汉字处理不友好,生成的图片title会显示如下图:

 解决方法:
1.引入第三方字体


2.代码中自定义字体解析器

InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("font/simsun.ttf");
        Font font = Font.createFont(TRUETYPE_FONT, inputStream);
        AWTFontResolver awtFontResolver = new AWTFontResolver();
        awtFontResolver.setFontMapping("simsun", font);

3.测试代码

public static void main(String[] args) {
        Map<String, Object> map = new HashMap<>();
        map.put("title", "标题");
        map.put("bg", "https://xxx/2021-07-22/ed91af576f3947d6ba60dcabfc3ca122.png");
        map.put("qrCode", "https://xxx/2021-07-22/ed91af576f3947d6ba60dcabfc3ca122.png");
        String url = turnImage("index.ftl", map);
    }

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值