Java通过freemarker实现导出PDF

  1. 制作模板
  2. 引入依赖
  3. 引入所需字体文件
  4. 工具类的编写
  5. 业务实现

一、模板制作
(1)编写html代码 ,需要替换的值与内容预留出来,用${name}代替,需循环处.表格前加上<#list listKey as t> ${t.name}
(2)将写好的html文件用文本打开,复制代码,用xml格式工具格式一下。最后将html文件后缀改为.ftl

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
            <title>PDF导出</title>
            <style type="text/css">
      *{
        box-sizing: border-box;
      }
      body{
        font-family: SimSun;
      }
      .content {
        width: 100%;
        height: 100%;
        text-align: center;
        font-size: 16px;
      }

      .contentHeader {
        height: 60px;
        line-height: 60px;
        font-size: 30px;
      }

      .title {
        width: 100%;
        height: 25px;
        line-height: 25px;
      }

      .titleLeft {
        padding-left: 20px;
        float: left;
      }

      .titleRight {
        padding-right: 20px;
        float: right;
      }

      table {
        width: 98%;
        height: 100%;
        border-collapse: collapse;
        text-align: center;
        font-size: 16px;
        margin: 0 2%;
      }

      td {
        padding: 8px;
      }

      .tdOne {
        width: 120px;
      }

      .footerTable {
        width: 98%;
        height: 100%;
        border-collapse: collapse;
        text-align: center;
        font-size: 16px;
      }
      .footerTd{
        border-bottom: 1px solid transparent;
      }
    </style>
        </head>
        <body>
            <div class='content'>
                <div class='contentHeader'>设备任务单</div>
                <div class='title'>
                    <span class='titleLeft'>所属组织: ${pkcompany}</span>
                    <span class='titleRight'>打印人:${psnname}</span>
                </div>
                <table border="1">
                    <tr>
                        <td class='tdOne'>标题</td>
                        <td class='tdTwo'>${contractno}设备任务单</td>
                        <td class='tdOne'>流水号</td>
                        <td class='tdTwo'>${pk_equtask}</td>
                    </tr>
                    <tr>
                        <td class='tdOne'>提交人</td>
                        <td class='tdTwo'>${creatorname}</td>
                        <td class='tdOne'>所属部门</td>
                        <td class='tdTwo'>${creatordepname}</td>
                    </tr>
                    <tr>
                        <td class='tdOne'>申请日期</td>
                        <td class='tdTwo'>${createdate}</td>
                        <td class='tdOne'>生产代码</td>
                        <td class='tdTwo'>${shengchandaima}</td>
                    </tr>
                    <tr>
                        <td class='tdOne'>合同号</td>
                        <td class='tdTwo'>${contractno}</td>
                        <td class='tdOne'>制号</td>
                        <td class='tdTwo'>${zhihao}</td>
                    </tr>
                    <tr>
                        <td class='tdOne'>客户所在地</td>
                        <td class='tdTwo'>${cusaddress}</td>
                        <td class='tdOne'>数量</td>
                        <td class='tdTwo'>1.0</td>
                    </tr>
                    <tr>
                        <td class='tdOne'>内部型号</td>
                        <td class='tdTwo'>${equxinghao_task}</td>
                        <td class='tdOne'>内部设备名称</td>
                        <td class='tdTwo'>${equname_task}</td>
                    </tr>
                    <tr>
                        <td class='tdOne'>合同型号</td>
                        <td class='tdTwo'>${innerEquxinghao}</td>
                        <td class='tdOne'>合同设备名称</td>
                        <td class='tdTwo'>${innerEquname}</td>
                    </tr>
                    <tr>
                        <td class='tdOne'>开始日期~要求交货时间</td>
                        <td class='tdTwo' colspan="3">${begindate}~${jiaohuodate}</td>
                    </tr>
                    <tr>
                        <td class='tdOne'>操作画面语言</td>
                        <td class='tdTwo'>${caozuoxitong}</td>
                        <td class='tdOne'>电气图纸语言</td>
                        <td class='tdTwo'>${def1}</td>
                    </tr>
                    <tr>
                        <td class='tdOne'>说明书语言</td>
                        <td class='tdTwo'>${def2}</td>
                        <td class='tdOne'>设备标识、标牌语言</td>
                        <td class='tdTwo'>${def3}</td>
                    </tr>
                    <tr>
                        <td class='tdOne'>电压要求</td>
                        <td class='tdTwo'>${dianya}</td>
                        <td class='tdOne'>CE认证</td>
                        <td class='tdTwo'>${cerenzheng}</td>
                    </tr>
                    <tr>
                        <td class='tdOne'>技术要求</td>
                        <td class='tdTwo'>${jishuyaoqiu}</td>
                        <td class='tdOne'>客户环境(温度)说明</td>
                        <td class='tdTwo'>${kehuhuanjing}</td>
                    </tr>
                    <tr>
                        <td class='tdOne'>所属制造部</td>
                        <td class='tdTwo'>${makedept}</td>
                        <td class='tdOne'>所属技术组</td>
                        <td class='tdTwo'>${tecdept}</td>
                    </tr>
                    <tr>
                        <td class='tdOne'>合同负责人</td>
                        <td class='tdTwo'>${salername}</td>
                        <td class='tdOne'>紧急程度</td>
                        <td class='tdTwo'>${jinjichengdu}</td>
                    </tr>
                    <tr>
                        <td colspan="4" class='footerTd'>审批记录</td>
                    </tr>
                </table>
                <table border="1" class='footerTable'>
                    <tr>
                        <td>节点名称</td>
                        <td>审批操作</td>
                        <td>审批意见</td>
                        <td>审批人</td>
                        <td>审批时间</td>
                    </tr>
                    <#list listKey as t>
                    <tr>
                        <td>${t.taskdefname}</td>
                        <td>${t.approveresult}</td>
                        <td>${t.approvecontentvalue}</td>
                        <td>${t.noticename}</td>
                        <td>${t.approvedatevalue}</td>
                    </tr>
                    </#list>
                </table>
            </div>
        </body>
    </html>

二、所需pom依赖

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

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

三、引入字体所需文件,我的放在resources下新建一个template ===》font目录下 simsun.ttc

在这里插入图片描述
四、实体类
没啥说的,自己去改路径,debug走一下,需要图片就放开注释的代码

```java
package com.tjk.tjkcom.util;


import com.lowagie.text.pdf.BaseFont;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.xhtmlrenderer.pdf.ITextRenderer;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.Locale;
import java.util.Map;

public class PDFTemplateUtil {

    /**
     * 通过模板导出pdf文件
     * @param data 数据
     * @param templateFileName 模板文件名
     * @throws Exception
     */
    public static ByteArrayOutputStream createPDF(Map<String,Object> data, String templateFileName) throws Exception {
        // 创建一个FreeMarker实例, 负责管理FreeMarker模板的Configuration实例
        Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        // 指定FreeMarker模板文件的位置
        cfg.setClassForTemplateLoading(PDFTemplateUtil.class,"/mailtemplate");
        ITextRenderer renderer = new ITextRenderer();
        OutputStream out = new ByteArrayOutputStream();
        try {
            // 设置 css中 的字体样式(暂时仅支持宋体和黑体) 必须,不然中文不显示
            renderer.getFontResolver().addFont("/mailtemplate/font/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            // 设置模板的编码格式
            cfg.setEncoding(Locale.CHINA, "UTF-8");
            // 获取模板文件
            Template template = cfg.getTemplate(templateFileName, "UTF-8");
            StringWriter writer = new StringWriter();
            // 将数据输出到html中
            template.process(data, writer);
            writer.flush();

            String html = writer.toString();
            // 把html代码传入渲染器中
            renderer.setDocumentFromString(html);

            // 设置模板中的图片路径 (这里的images在resources目录下) 模板中img标签src路径需要相对路径加图片名 如
//            String url = PDFTemplateUtil.class.getClassLoader().getResource("images").toURI().toString();
//            renderer.getSharedContext().setBaseURL(url);
            renderer.layout();

            renderer.createPDF(out, false);
            renderer.finishPDF();
            out.flush();
            return (ByteArrayOutputStream)out;
        } finally {
            if(out != null){
                out.close();
            }
        }
    }
}

五、业务实现
(1)写你的代码,controller -service -serviceimpl - mapper

package com.example.demo.controller;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/pdf")
public class PdfController {

    @RequestMapping("/export")
    public void exportPdf(HttpServletResponse response) throws Exception{
        ByteArrayOutputStream baos = null;
        OutputStream out = null;
        try {
            // 模板中的数据,实际运用从数据库中查询
            ------------------------------------
            ------------------------------------
            ------------------------------------

           baos = PDFTemplateUtil.createPDF(resultMap, "Test.ftl");
                // 设置响应消息头,告诉浏览器当前响应是一个下载文件
                response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
                response.setCharacterEncoding("utf-8");
                response.setContentType("application/x-msdownload");
                // 告诉浏览器,当前响应数据要求用户干预保存到文件中,以及文件名是什么 如果文件名有中文,必须URL编码
                String fileName = URLEncoder.encode("设备任务单:"+hashMap.get("contractno").toString()+".pdf", "UTF-8");
                response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
                /*response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));*/
                out = response.getOutputStream();
                baos.writeTo(out);
                baos.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("导出失败:" + e.getMessage());
        } finally{
            if(baos != null){
                baos.close();
            }
            if(out != null){
                out.close();
            }
        }
    }
}

六、最后建议,前后分离,如果调不通,看看前端代码,console.log(error) 多输出日志,debug跟踪一下

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值