Thymeleaf实现自定义模板导出pdf或word

Posted 萧何~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Thymeleaf实现自定义模板导出pdf或word相关的知识,希望对你有一定的参考价值。

技术栈:springboot+thymeleaf+pdf引擎

1.导入对应的jar包,使用srpingboot快速实现

       <!--引入thymeleaf相关的依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
 <!--用于pdf的页面渲染自带webkit浏览器内核-->
        <dependency>
            <groupId>com.openhtmltopdf</groupId>
            <artifactId>openhtmltopdf-core</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.openhtmltopdf</groupId>
            <artifactId>openhtmltopdf-pdfbox</artifactId>
            <version>1.0.0</version>
        </dependency>

2.生成模板的java代码实现,文件路径需要修改您对应的位置

 /**
     * 本地
     *构建一个pdf
     * @param templateName 模板名称
     * @param variables    模板变量
     * @throws Exception
     */
    public static void buildResource( String templateName, Map<String, Object> variables) throws Exception {
        //thymeleaf构造模板引擎;给html文件赋值
        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
        //默认是找classpath路径下的资源
        resolver.setPrefix("testPDF/templates/");
        resolver.setSuffix(".html");//模板文件后缀
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(resolver);
        //构造上下文
        Context context = new Context();
        context.setVariable("templateName",templateName);
        //设置变量
        context.setVariables(variables);
        //TODO 渲染模板,返回的生成的模板的字符串
        String example = templateEngine.process("parent", context);
        // 生成pdf文件地址
        String pdfPath ="D://"+ new Random().nextInt(30) + "-" + System.nanoTime() + ".pdf";
        File file = new File(pdfPath);
        file.createNewFile();
        FileOutputStream os = new FileOutputStream(file);
        //构建pdf的预览
        PdfRendererBuilder builder = new PdfRendererBuilder();
        //设置字体支持中文
        builder.useFont(new ClassPathResource("testPDF/fonts/simsun.ttf").getFile(), "simsun");
        //使用快速渲染器
        builder.useFastMode();

        //String s = ResourceUtils.getURL("testPDF/templates/").toString(); 获取资源路径
        String path = new ClassPathResource("/testPDF/templates").getPath();//获取项目下的资源路径
        //withHtmlContent()参数一是模板,参数二模板的基础路径
        builder.withHtmlContent(example,new ClassPathResource("/testPDF/templates").getPath());
        //输出pdf的结果
        builder.toStream(os);
        builder.run();
        //设置字符编码
        PrintWriter writer = new PrintWriter(new OutputStreamWriter(os));
        writer.flush();
        writer.close();
    }

    /**
     * TODO 通过接口接口请求生成pdf模板;有pdf预览窗口
     * @param templateName
     * @param variables
     * @throws Exception
     */
    public static void requestBuildResource(HttpServletResponse response, String templateName, Map<String, Object> variables) throws Exception {
        //thymeleaf构造模板引擎;给html文件赋值
        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
        //默认是找classpath路径下的资源
        resolver.setPrefix("testPDF/templates/");
        resolver.setSuffix(".html");//模板文件后缀
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(resolver);
        //构造上下文(Model)
        Context context = new Context();
        //设置变量
        context.setVariables(variables);
        //TODO 渲染模板,返回的生成的模板的字符串
        String example = templateEngine.process(templateName, context);

        //TODO 生成pdf,浏览器进行展示
        response.setHeader("Content-Disposition", "filename=" + new String(("pdfFileName" + ".pdf").getBytes(), "iso8859-1"));
        //生成pdf,浏览器不进行展示,默认附件下载;原因:attachment标记以附件方式下载保存
        // response.setHeader("Content-Disposition", "attachment;fileName=" + new String(("templateName" + ".pdf").getBytes("gb2312"), "ISO8859-1"));
        OutputStream os = response.getOutputStream();
        //构建pdf的构造器
        PdfRendererBuilder builder = new PdfRendererBuilder();
        //设置字体支持中文
        //
        builder.useFont(new ClassPathResource("testPDF/fonts/simsun.ttf").getFile(), "simsun");
        builder.useFastMode();
        //withHtmlContent()参数:提供一个包含要转换为PDF的XHTML/XML的字符串
        //ResourceUtils.getURL()获取资源的地址
        builder.withHtmlContent(example, ResourceUtils.getURL("testPDF/templates/").toString());
        //输出pdf的结果
        builder.toStream(os);
        builder.run();
        //设置字符编码
        PrintWriter writer = new PrintWriter(new OutputStreamWriter(os));
        writer.flush();
        writer.close();
    }


    /**
     * 生成本地word
     * @param variables 模板需要的数据
     * @throws Exception
     */
    public static void buildWord( Map<String, Object> variables) throws Exception {

        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
        //默认是找classpath路径下的资源
        resolver.setPrefix("testPDF/templates/");
        resolver.setSuffix(".html");//模板文件后缀
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(resolver);
        //构造上下文
        Context context = new Context();

        context.setVariables(variables);
        // 生成word文件地址
        String pdfPath ="D://"+ new Random().nextInt(30) + "-" + System.nanoTime() + ".docx";
        File file = new File(pdfPath);
        file.createNewFile();
        FileOutputStream os = new FileOutputStream(file);

        try( PrintWriter writer = new PrintWriter(new OutputStreamWriter(os))) {
            //TODO 参数一是模板;参数二:上下文数据模板需要读取的数据容器;参数三writer输出流是指定输出到那个地方
            templateEngine.process("one",context, writer);
        }catch (Exception e){
            log.error("导出word文件出错啦:{}", e.getMessage());
        }
    }

    /**
     * 通过接口生成word
     * @param response
     * @param variables
     * @throws Exception
     */
    public static void requestbuildWord(HttpServletResponse response, Map<String, Object> variables) throws Exception {

        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
        //默认是找classpath路径下的资源
        resolver.setPrefix("testPDF/templates/");
        resolver.setSuffix(".html");//模板文件后缀
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(resolver);
        //构造上下文
        Context context = new Context();
        context.setVariable("templateName", "one");
        context.setVariables(variables);
        // 生成word文件地址
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/msword");
        response.setHeader("Content-Disposition", "attachment;fileName=" + new String(("test" + ".xls").getBytes("gb2312"), "ISO8859-1"));
        try( PrintWriter writer = new PrintWriter(new OutputStreamWriter(response.getOutputStream()))) {
            //TODO 参数一是模板;参数二:上下文数据模板需要读取的数据容器;参数三writer输出流是指定输出到那个地方
            templateEngine.process("parent",context, writer);
        }catch (Exception e){
            log.error("导出word文件出错啦:{}", e.getMessage());
        }
    }

3.thymeleaf模板代码,自定义模板需要了解thymeleaf语法,可自行搜索thymeleaf官网学习

注意导出pdf一定要用这个parent父页面,先引入执行,原因父页面设置的中文编码的使用,防止导出中文乱码

parent页面代码

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="UTF-8"/>
    <title >父页面</title>
    <style>
        @page {
            size: A4;
            @top-center {
                content: element(header);
            }
            @bottom-center {
                content: \'自由行产品详情\';
                font-family: \'simsun\', serif;
            }
        }

        html, body {
            font-family: \'simsun\', serif;
        }

        table {
            -fs-table-paginate: paginate;
            border-collapse: collapse;
        }

        table, td, th {
            border: 1px solid #555;
            padding: 3px 5px;
        }

        th {
            background-color: #eff3fa;
        }

        #page-header {
            position: running(header);
            border-bottom: 1px solid #555;
            padding: 5px;
        }

        #page-header-text {
            font-size: 16px;
        }

        #page-header-num:after {
            float: right;
            text-align: right;
            content: counter(page) \'/\' counter(pages);
        }
    </style>
</head>
<body>
<div id="page-header">
    <span id="page-header-text">kindleboy</span>
    <span id="page-header-num"></span>
</div>
<div th:include="${templateName}::body"></div>
</body>
</html>
parent页面

测试模板页面代码,自行编辑

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
</head>
<body>
<div>
    <p>测试导出pdf</p>
    <p th:text="\'weclcome to guangzhou,\'+${user.username}">静态数据</p>
</div>
</body>
</html>

字体中文设置文件:simsun.ttf

下面链接获取设置simsun.tff文件链接

链接:https://pan.baidu.com/s/1FkGDX9VcM4XNAlLuvvDQmA
提取码:tdqa

注意功能发布到linux服务器上,读取字体文件一定要用流的方式读取simsun.tff文件,防止读取不了

 

以上是关于Thymeleaf实现自定义模板导出pdf或word的主要内容,如果未能解决你的问题,请参考以下文章

Thymeleaf常用语法:自定义数据转换类

Dynamics 365Online PDF导出及打印

Dynamics 365Online PDF导出及打印

Dynamics 365Online PDF导出及打印

如何使用 thymeleaf 作为模板引擎生成 pdf 报告? [关闭]

Magicodes.IE基础教程之导出Pdf