0
点赞
收藏
分享

微信扫一扫

如何使用FTL模版,快速将数据导出到自定义PDF文件中

在java后端,使用ftl模版将数据导出到自定义pdf文件中的基本操作流程如下

如何使用FTL模版,快速将数据导出到自定义PDF文件中_html

其实操作并不复杂,关键在于FTL模版的创建和转换成PDF文件这两步操作上。

ftl,即freemarker template language,Freemarker其实是一种比较简单的网页展示技术,说白了就是网页模板和数据模型的结合体。据个人理解,Freemarker大致的工作方式是,网页模板里面嵌入了数据模型中的数据、Freemarker自定义流程控制语言、Freemarker自定义的操作函数等等,在装载网页的时候,Freemarker模板自动从数据模型中提取数据,并解释整个网页为我们熟知的HTML页面。

创建ftl文件的一个方便快捷的玩法是,先创建一个html文件,调整好样式布局后,修改文件后缀为ftl即可。贴出我的ftl文件代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"></meta>
    <title>学校网上报名新生个人信息表(<#if level == 1>小学<#else>初中</#if>)</title>
    <style>
        td {
            padding: 4pt 0;
        }
        div{
            margin: 0;
            padding: 0;
        }
        h2{
            margin: 0;
            padding: 0;
            margin-bottom: 8pt;
        }
        p{
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body style="font-family: SimSun;">
<div style="width: 517pt;margin: auto;text-align: center;color: #000000">
    <h2 style="text-align: center">学校网上报名新生个人信息表(<#if level == 1>小学<#else>初中</#if>)</h2>
    <div>
        <table width="100%" border="1" cellpadding="0" cellspacing="0">
            <tr>
                <td style="width: 64pt">学生姓名</td>
                <td style="width: 65pt">${data.studentName!''}</td>
                <td style="width: 64pt">性别</td>
                <td style="width: 60pt">${data.studentSex!''}</td>
                <td style="width: 66pt">出生年月日</td>
                <td style="width: 70pt">${data.studentBirth!''}</td>
                <td style="width: 64pt">民族</td>
                <td style="width: 64pt">${data.studentNation!''}</td>
            </tr>
            <#if level == 1>
                <tr>
                    <td colspan="2">身份证号码</td>
                    <td colspan="3">${data.studentIdcardNo!''}</td>
                    <td colspan="2">健康状况</td>
                    <td>${data.health!''}</td>
                </tr>
            </#if>
            <#if level == 2>
                <tr>
                    <td>身份证号码</td>
                    <td colspan="2">${data.studentIdcardNo!''}</td>
                    <td>毕业小学</td>
                    <td colspan="2">${data.byxx}</td>
                    <td>健康状况</td>
                    <td>${data.health!''}</td>
                </tr>
            </#if>
            <tr>
                <td rowspan="4"><p>少</p><p>年</p><p>儿</p><p>童</p><p>户</p><p>籍</p><p>居</p><p>住</p><p>情</p>况</td>
                <td>户籍所属派出所</td>
                <td colspan="2"><#if data.isBlshj == 1>${data.policeStationName!''}<#else>${data.policeStation!''}</#if></td>
                <td>户籍属地</td>
                <td colspan="3">${data.hjTownName!''}${data.hjVillageName!''}</td>
            </tr>
            <tr>
                <td>户籍地址</td>
                <td colspan="6">${data.hjAddress!''}</td>
            </tr>
            <tr>
                <td>拟申请就读学校辖区内的房产地址</td>
                <td colspan="6">${data.fcTownName!''}${data.fcVillageName!''}${data.fcGroupName}</td>
            </tr>
            <tr>
                <td>房产证持有人姓名</td>
                <td>${data.fczHolder!''}</td>
                <td>房产证、不动产权证书或购房合同编号</td>
                <td>${data.fcNo!''}</td>
                <td>少年儿童与房产证、不动产权证书或购房合同持有人的关系</td>
                <td colspan="2">${data.relation!''}</td>
            </tr>
            <tr>
                <td rowspan="3"><p>家</p><p>庭</p><p>情</p>况</td>
                <td>父</td>
                <td>姓名</td>
                <td colspan="2">${data.fatherName!''}</td>
                <td>联系电话</td>
                <td colspan="2">${data.fatherPhone!''}</td>
            </tr>
            <tr>
                <td>母</td>
                <td>姓名</td>
                <td colspan="2">${data.motherName!''}</td>
                <td>联系电话</td>
                <td colspan="2">${data.motherPhone!''}</td>
            </tr>
            <tr>
                <td colspan="2"><p>法定监护人</p>(孤儿填写)</td>
                <td colspan="2">${data.fdjhrName!''}</td>
                <td>联系电话</td>
                <td colspan="2">${data.fdjhrPhone!''}</td>
            </tr>
            <tr>
                <td colspan="8"></td>
            </tr>
            <tr>
                <td colspan="3">拟申请就读学校</td>
                <td colspan="5">${data.applySchoolName!''}</td>
            </tr>
            <tr>
                <td colspan="8" style="text-align: left;padding-left: 6pt">
                    <p>申请理由(在○内打√):</p>
                    <p><#if data.type == 'A'>√<#else>○</#if> A.少年儿童具有就读学校服务范围内户籍。</p>
                    <p><#if data.type == 'B'>√<#else>○</#if> B.政策性照顾生。</p>
                    <p><#if data.type == 'C'>√<#else>○</#if> C.法定监护人房产在拟申请就读学校辖区内。</p>
                    <p><#if data.type == 'D'>√<#else>○</#if> D.法定监护人城区无独立房产,户籍不在城区,但具备进城务工随迁子女入学的条件。</p>
                </td>
            </tr>
            <tr>
                <td>入学类型审定</td>
                <td colspan="3"></td>
                <td>证明材料学校审核人签名</td>
                <td colspan="3"></td>
            </tr>
            <tr>
                <td>家长签名</td>
                <td colspan="3"></td>
                <td>网上信息核定人签名</td>
                <td colspan="3"></td>
            </tr>
        </table>
        <div style="text-align: left;margin-top: 8pt">
            <p style="font-weight: bolder">备注:</p>
            <p style="text-indent: 2em">1.此表信息均为真实信息。凡是发现家长提供入学虚假证件等报名材料的,一经查实,其子女一律取消城区义务教育学校就读资格,并进一步追究相关人员的责任。</p>
            <p style="text-indent: 2em">2.学生需提交房产证(或不动产权证书)、户口簿、小学毕业证(就读初中需要提交)等原件、复印件到拟申请就读学校,由学校现场审验,审核人须在复印件上签名。</p>
            <p style="text-indent: 2em">3.2023年城区<#if level == 1>小学<#else>初中</#if>入学报名均用此表。</p>
            <p style="text-indent: 2em">4.凡是报读D类少年儿童必须具备进城务工人员随迁子女入学细则所需证件。</p>
        </div>
    </div>
</div>
</body>
</html>

上述代码创建了一个报名信息的表格文件,使用Freemarker渲染数据。有一点需要特别注意,即ftl文件要求所有标签成对闭合,因为默认创建的html文件的meta表情是这样:

<meta charset="UTF-8">

我们需要手动修改为这样:

<meta charset="UTF-8"></meta>

否则模版无法正常渲染,后端会报错。

ftl模版文件准备好之后,我们需要在后端处理获取模版文件,查询模版需要的数据,并渲染生成一个HTML文件,示例代码如下:

public String createApplyPdf(String applyId, Integer level) throws AppException,Exception {
        // 获取或创建一个模版
        Configuration configuration = new Configuration();
        configuration.setDirectoryForTemplateLoading(new File(resourcePath + File.separator + "temp"));
        configuration.setDefaultEncoding("UTF-8");
        Template template = configuration.getTemplate("apply.ftl");
        String fileName = (level == 1 ? "P" : "M") + ToolUtil.md5(String.valueOf(applyId));
        String html = resourcePath + File.separator + "temp" + File.separator + fileName + ".html";

        //设置文件输入流编码
        OutputStream os = new FileOutputStream(html);
        OutputStreamWriter osw = new OutputStreamWriter(os, StandardCharsets.UTF_8);

        // 将页面中要展示的数据放入一个map中
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("level", level);
        if(level == 1) {
            PrimarySchoolApply primarySchoolApply = primarySchoolApplyService.info(applyId);
            map.put("data", primarySchoolApply);
        }else if(level == 2) {
            MiddleSchoolApply middleSchoolApply = middleSchoolApplyService.info(applyId);
            map.put("data", middleSchoolApply);
        }

        //将map中的数据输入到模板文件中
        template.process(map, osw);
        osw.close();

        //html转成PDF文档
        String pdf = resourcePath + File.separator + "temp" + File.separator + fileName + ".pdf";
        ToolUtil.convertPdf(html, pdf, fontPath);
        return File.separator + "temp" + File.separator + fileName + ".pdf";
    }

需要引入freemarker的依赖,在pom.xml文件中添加:

<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.28</version>
</dependency>

上面的代码末尾调用了将html文件转成pdf文件的方法,该操作我们可以使用ITextRenderer的方法,在pom.xml中引入依赖

<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>flying-saucer-pdf</artifactId>
    <version>9.1.5</version>
</dependency>

转换pdf文件的代码比较简单

public static void convertPdf(String inputPath, String outPath, String fontPath){
    try {
        OutputStream os = new FileOutputStream(outPath);

        ITextRenderer renderer = new ITextRenderer();

        ITextFontResolver fontResolver = renderer.getFontResolver();
        //启动中文支持
        fontResolver.addFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);

        String url = new File(inputPath).toURI().toURL().toString();
        renderer.setDocument(url);
        renderer.layout();
        renderer.createPDF(os);
        os.close();
    }catch (Exception e){
        e.printStackTrace();
    }
}

注意需要启动中文支持,否则中文会乱码。生成的PDF效果图下图所示

如何使用FTL模版,快速将数据导出到自定义PDF文件中_模版_02

举报

相关推荐

0 条评论