SpringBoot pdf打印及预览(openhtmltopdf+freemarker)

 更新时间:2023年05月23日 11:19:04   作者:多喝灬丶烫水  
这篇文章主要介绍了SpringBoot pdf打印及预览(openhtmltopdf+freemarker)

SpringBoot pdf打印及预览(openhtmltopdf+freemarker)

添加依赖

openhtmltopdf+freemarker

<properties>
        <openhtml.version>1.0.10</openhtml.version>
    </properties>
<!--openhtmltopdf -->
   <dependencies>
        <dependency>
            <!-- ALWAYS required, usually included transitively. -->
            <groupId>com.openhtmltopdf</groupId>
            <artifactId>openhtmltopdf-core</artifactId>
            <version>${openhtml.version}</version>
        </dependency>
        <dependency>
            <!-- Required for PDF output. -->
            <groupId>com.openhtmltopdf</groupId>
            <artifactId>openhtmltopdf-pdfbox</artifactId>
            <version>${openhtml.version}</version>
        </dependency>
        <dependency>
            <!-- Optional, leave out if you do not need logging via slf4j. -->
            <groupId>com.openhtmltopdf</groupId>
            <artifactId>openhtmltopdf-slf4j</artifactId>
            <version>${openhtml.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
  </dependencies>

在/resources/template/view/html新建模板xxx.ftl文件

<html>
<head>
    <meta charset="UTF-8"/>
    <style>
    /* 特有css样式自行参考官网 */
        @page {
            size: a4;
            @top-left {
                content: element(header-left);
            }
            @top-center {
                content: element(header-center);
            }
            @top-right {
                content: element(header-right);
            }
            @bottom-center {
                font-size: 14px;
                content: counter(page);
                font-family: 'simsun', serif;
            }
            margin: 50px;
        }
        * {
            margin: 0;
            padding: 0;
            font-family: 'simsun', serif;
        }
        #page-header-left {
            font-size: 10px;
            font-weight: bold;
            position: running(header-left);
        }
        #page-header-center {
            font-size: 10px;
            font-weight: bold;
            position: running(header-center);
        }
        #page-header-right {
            font-size: 10px;
            font-weight: bold;
            position: running(header-right);
        }
        table {
            width: 100%;
            font-size: 14px;
            border-collapse: collapse;
            font-family: 'simsun', serif;
            border-spacing: 0;
            /* The magical table pagination property. */
            /*-fs-table-paginate: paginate;*/
            /* Recommended to avoid leaving thead on a page by itself. */
            -fs-page-break-min-height: 0.5cm;
            border-left: 0.07cm solid black;
            border-right: 0.07cm solid black;
            border-bottom: 0.03cm solid black;
        }
        .checkbox {
            display: inline-block;
            position: relative;
            top: 1px;
            width: 10px;
            height: 10px;
            border: 1px solid black;
        }
        .correct {
            display: inline-block;
            position: relative;
            top: 2px;
            right: 15px;
            width: 7px;
            height: 3px;
            border-left: 1px solid black;
            border-bottom: 1px solid black;
            -webkit-transform: rotate(-45deg);
            transform: rotate(-45deg);
            margin-right: -16px;
        }
        input[type = "checkbox"] {
            width: 10px;
            height: 10px;
            border: 1px solid black;
        }
        tr, thead, tfoot {
            page-break-inside: avoid;
        }
        td, th {
            page-break-inside: avoid;
            font-family: 'simsun', serif;
            padding: 1px;
            border-top: 0.03cm solid black;
            border-left: 0.03cm solid black;
        }
        td:first-child, th:first-child {
            border-left: 0;
        }
        #table-title {
            text-align: center;
            margin-top: 0;
            margin-bottom: 5px;
            font-weight: bold;
        }  
    </style>
</head>
<body>
<div class="header-box">
    <div id="page-header-left">
        <span id="page-header-text">编号:<span style="font-weight: normal">${code!''}</span></span>
    </div>
    <div id="page-header-center">
    <span id="page-header-text">时间 <sup>1)</sup>:<span
                style="font-weight: normal">${time?date!''}</span></span>
    </div>
</div>
<div class="basic-box">
    <table style="border-top: 0;">
        <tr>
            <td>标题1</td>
            <td>${xx1!''}</td>
            <td>标题2</td>
            <td>${xx2!''}</td>
            <td>标题3</td>
            <td>${xx3!''}</td>
        </tr>
         <tr>
            <td style="font-weight: bold;text-align: left;">结果</td>
            <td colspan="3" style="text-align: left;">
                <div>
                    <div class="checkbox"></div>
                    <#if result??&&result == '1'>
                        <div class="correct"></div>
                    </#if>
                    <div style="display: inline-block">合格</div>
                    <div class="checkbox"></div>
                    <#if result??&&result == '0'>
                        <div class="correct"></div>
                    </#if>
                    <div style="display: inline-block">不合格</div>
                </div>
            </td>
            <td colspan="4" style="font-weight: bold;text-align: left;">签字人:</td>
        </tr>
    </table>
</div>
</body>
</html>

controller接口

@RequestMapping(value = "/print/pdf/[code]", produces = MediaType.APPLICATION_PDF_VALUE)
    public ResponseEntity<byte[]> printPdf(@PathVariable("code") String detectCode) throws IOException, TemplateException {
        Assert.hasText(code, "code不能为空");
        return detectReportPrintService.findPdf(code);
    }

service实现类

📌pdf预览有中文乱码,需要重新引入simsun.ttf字体文件,放在/resources/fonts文件夹下(与代码路径一致即可),ftl文件中css样式必须font-family: 'simsun', serif;

📌在 Configuration 中可以使用下面的方法来方便建立三种模板加载。 (每种方法都会在其内部新建一个模板加载器对象,然后创建 Configuration 实例来使用它。)

1. void setDirectoryForTemplateLoading(File dir);

2. void setClassForTemplateLoading(Class cl, String prefix);

3. void setServletContextForTemplateLoading(Object servletContext, String path);

项目打包为jar包只能使用setClassForTemplateLoading方法。

public ResponseEntity<byte[]> findPdf(String code) throws IOException, TemplateException {
        //获取ftl所需变量值的自定义方法
        Map data = this.findValue(code);
        //FreeMarker 生成 html字符串
        Configuration conf = new Configuration(Configuration.VERSION_2_3_23);
        conf.setDefaultEncoding("UTF-8");
        //加载模板文件(模板的路径)
        //有多种加载模板的方法
        //项目打包为jar包只能使用setClassForTemplateLoading方法
        //第一个参数:springboot启动类,第二个参数:ftl模板对应resources下的位置
        conf.setClassForTemplateLoading(XaWebApplication.class, "/template/view/html");
        // 加载模板
        Template template = conf.getTemplate("/xxx.ftl");
        //传入变量生成html字符串
        String htmlString = FreeMarkerTemplateUtils.processTemplateIntoString(template, data );
        //openhtmltopdf生成pdf
        @Cleanup ByteArrayOutputStream os = new ByteArrayOutputStream();
        PdfRendererBuilder builder = new PdfRendererBuilder();
        builder.withHtmlContent(htmlString, "");
        builder.useFont(new FSSupplier<InputStream>() {
            @SneakyThrows
            @Override
            public InputStream supply() {
                return resourceLoader.getResource("classpath:fonts/simsun.ttf").getInputStream();
            }
        }, "simsun");
        builder.toStream(os);
        builder.run();
        byte[] bytes = os.toByteArray();
        return new ResponseEntity<>(bytes, HttpStatus.OK);
    }

以上就是SpringBoot pdf打印及预览(openhtmltopdf+freemarker)的详细内容,更多关于SpringBoot pdf打印预览的资料请关注脚本之家其它相关文章!

相关文章

  • SpringBoot+OCR实现PDF内容识别的示例代码

    SpringBoot+OCR实现PDF内容识别的示例代码

    在SpringBoot中,您可以结合OCR库来实现对PDF文件内容的识别和提取,本文就来介绍一下如何使用 Tesseract 和 pdf2image 对 PDF 文件进行OCR识别和提取,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • 使用HTTPclient保持长连接

    使用HTTPclient保持长连接

    这篇文章主要介绍了使用HTTPclient保持长连接,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • Java多线程和并发基础面试题(问答形式)

    Java多线程和并发基础面试题(问答形式)

    多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一。在这里,从面试的角度列出了大部分重要的问题,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • 详解如何解决SSM框架前台传参数到后台乱码的问题

    详解如何解决SSM框架前台传参数到后台乱码的问题

    这篇文章主要介绍了详解如何解决SSM框架前台传参数到后台乱码的问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • Java Spring的两种事务你知道吗

    Java Spring的两种事务你知道吗

    这篇文章主要为大家详细介绍了Java Spring的两种事务,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • Springboot实现XSS漏洞过滤的示例代码

    Springboot实现XSS漏洞过滤的示例代码

    这篇文章主要介绍了Springboot实现XSS漏洞过滤的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • Java行为型设计模式之外观设计模式详解

    Java行为型设计模式之外观设计模式详解

    外观模式为多个复杂的子系统,提供了一个一致的界面,使得调用端只和这个接口发生调用,而无须关系这个子系统内部的细节。本文将通过示例详细为大家讲解一下外观模式,需要的可以参考一下
    2022-11-11
  • 基于javaMybatis存进时间戳的问题

    基于javaMybatis存进时间戳的问题

    这篇文章主要介绍了javaMybatis存进时间戳的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Mybatis-plus自动填充不生效或自动填充数据为null原因及解决方案

    Mybatis-plus自动填充不生效或自动填充数据为null原因及解决方案

    本文主要介绍了Mybatis-plus自动填充不生效或自动填充数据为null原因及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • Nacos客户端配置中心缓存动态更新实现源码

    Nacos客户端配置中心缓存动态更新实现源码

    这篇文章主要为大家介绍了Nacos客户端配置中心缓存动态更新实现源码,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-03-03

最新评论