spring boot 生成PDF模板文件

1、主要目录

在这里插入图片描述
2、maven依赖

<!--工具类依赖-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.19</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>

        <!--pdf-->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity</artifactId>
            <version>1.7</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>html2pdf</artifactId>
            <version>4.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>font-asian</artifactId>
            <version>7.2.3</version>
        </dependency>

3、新建一个demo.html静态文件,后续导出模板就是按照此文件进行的

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8"/>
</head>
<body>
<div class="contianer">
    <div class="bg-img-container">
    </div>
    <h1>模板pdf</h1>
    <div class="flex-div">
        <p>表1</p>
    </div>

    <table border="1" cellSpacing="1">
        <tr>
            <th>姓名</th>
            <td colspan="3">$!{name}</td>
        </tr>
        <tr>
            <th #if($!{gender}==1) class="blue" #else class="red" #end>性别</th>
            <td colspan="3">
                #if($!{gender}==1)
                男
                #else
                女
                #end
            </td>
        </tr>
        <tr>
            <th>出生日期</th>
            <td>$!{birthDate}</td>
            <th>联系方式</th>
            <td>$!{phone}</td>
        </tr>
    </table>
    <h1>双重For循环取值</h1>
    <div class="flex-div">
        <p>表2</p>
    </div>
    <table border="1" cellSpacing="1">
        <tr>
            <th>学历</th>
            <th>学科</th>
            <td class="gray-bg">分数</td>
        </tr>
        #foreach($item in $eduList)
        <tr>
            <th  #set($len= $item.size+1) rowspan="$len">$item.name</th>
            #foreach($result in $item.itemList)
        <tr>
            <td>$velocityCount、$result.subject</td>
            <td #if($result.num > 60) class="green" #else class="red" #end>$result.num</td>
        </tr>
        #end
        </tr>
        #end
    </table>

</div>

</body>
<style>
    .blue {
        color: #244385;
        margin-left: 30px;
    }

    .green {
        color: #52c41a;
        margin-left: 30px;
    }

    .red {
        color: #c1181e;
        margin-left: 30px;
    }

    .flex-div {
        margin: 30px 0 15px;
        display: flex;
        align-items: center;
    }

    .line {
        width: 540px;
        height: 0px;
        border: dashed 1px #edf0f5;
    }

    table {
        width: 700px;
        border-collapse: collapse;
        /*border-spacing: 0;*/
        border-left: 1px solid #edf0f5;
        border-top: 1px solid #edf0f5;
    }

    th, td {
        border-right: 1px solid #edf0f5;
        border-bottom: 1px solid #edf0f5;
        padding: 5px 15px;
    }

    h1 {
        text-align: center;
        font-family: 'Microsoft YaHei';
        line-height: 60px;
        letter-spacing: 8px;
        color: #244385;
    }

    p {
        font-family: 'Microsoft YaHei';
        font-size: 20px;
        font-weight: normal;
        color: #244385;
        margin: 0 16px;
    }

    th {
        background-color: rgba(0, 0, 0, 0.01);
        width: 90px;
        min-width: 90px;
        max-width: 90px;
        text-align: left;
        text-indent: 10px;
        font-family: 'Microsoft YaHei';
        font-size: 16px;
        font-weight: normal;
        font-stretch: normal;
        line-height: 48px;
        letter-spacing: 2px;
        color: #666666;
    }

    td {
        font-size: 16px;
        color: #000000;
        text-align: left;
        text-indent: 10px;
        padding-right: 20px;
        height: 50px;
    }

    table,tr, th, td {
        border: solid 1px #edf0f5;
    }

    .gray-bg {
        background-color: rgba(0, 0, 0, 0.01);
    }
</style>
</html>


4、新建PdfUtil工具类

import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.font.FontProvider;
import org.apache.velocity.Template;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.context.Context;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;

import java.io.OutputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;

/**
 * PDF工具
 *
 * @author ppp
 * @date 2022/8/5
 */
public class PdfUtil {

    static {
        // Velocity初始化
        Velocity.setProperty(RuntimeConstants.OUTPUT_ENCODING, StandardCharsets.UTF_8);
        Velocity.setProperty(RuntimeConstants.INPUT_ENCODING, StandardCharsets.UTF_8);
        Velocity.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
        Velocity.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        Velocity.init();
    }


    /**
     * 据模板生成pfd格式文件
     *
     * @param context      上下文对象
     * @param template     pdf模板
     * @param outputStream 生成ofd文件输出流
     */
    public static void pdfFile(Context context, String template, OutputStream outputStream) {
        try (PdfWriter pdfWriter = new PdfWriter(outputStream)) {
            PdfDocument pdfDocument = new PdfDocument(pdfWriter);
            pdfDocument.setDefaultPageSize(PageSize.A4);

            ConverterProperties properties = new ConverterProperties();
            FontProvider fontProvider = new FontProvider();
            // 字体设置,解决中文不显示问题
            PdfFont sysFont = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H");
            fontProvider.addFont(sysFont.getFontProgram(), "UniGB-UCS2-H");
            properties.setFontProvider(fontProvider);

            Template pfdTemplate = Velocity.getTemplate(template, "UTF-8");
            StringWriter writer = new StringWriter();
            pfdTemplate.merge(context, writer);
            HtmlConverter.convertToPdf(writer.toString(), pdfDocument, properties);
            pdfDocument.close();
        } catch (Exception e) {
            throw new RuntimeException("PFD文件生成失败", e);
        }
    }

}

5、Controller接口测试,也可以根据业务来分层service

package com.example.springboot3.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.URLUtil;
import com.example.springboot3.utils.PdfUtil;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.velocity.VelocityContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

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

    @GetMapping("/getPdf")
    public void get(HttpServletResponse response){
        response.reset();
        response.setContentType("application/pdf");
        String filename = System.currentTimeMillis()+".pdf";
        response.addHeader("Content-Disposition", "inline; filename=" + URLUtil.encode(filename, CharsetUtil.CHARSET_UTF_8));
        VelocityContext context = new VelocityContext();

        context.put("name", "彭也行");
        context.put("gender", 1);
        context.put("birthDate", DateUtil.formatDateTime(new Date()));
        context.put("phone", "13666666666");

        List<Map<String, Object>> eduList = new ArrayList<>();
        // 小学
        Map<String, Object> primarySchoolMap = new HashMap<>();
        primarySchoolMap.put("name", "小学");
        List<Map<String, Object>> scoreList = new ArrayList<>();
        // 语文成绩
        Map<String, Object> chineseScore = new HashMap<>();
        chineseScore.put("subject", "语文");
        chineseScore.put("num", 60);
        // 数学成绩
        Map<String, Object> mathScore = new HashMap<>();
        mathScore.put("subject", "数学");
        mathScore.put("num", 99);
        scoreList.add(chineseScore);
        scoreList.add(mathScore);
        primarySchoolMap.put("itemList", scoreList);
        primarySchoolMap.put("size", scoreList.size());

        // 初中
        Map<String, Object> middleSchoolMap = new HashMap<>();
        middleSchoolMap.put("name", "初中");
        List<Map<String, Object>> middleScoreList = new ArrayList<>();
        // 语文成绩
        Map<String, Object> middleChineseScore = new HashMap<>();
        middleChineseScore.put("subject", "语文");
        middleChineseScore.put("num", 60);
        // 数学成绩
        Map<String, Object> middleMathScore = new HashMap<>();
        middleMathScore.put("subject", "数学");
        middleMathScore.put("num", 99);
        // 英语
        Map<String, Object> middleEnScore = new HashMap<>();
        middleEnScore.put("subject", "英语");
        middleEnScore.put("num", 55);

        middleScoreList.add(middleChineseScore);
        middleScoreList.add(middleMathScore);
        middleScoreList.add(middleEnScore);
        middleScoreList.add(middleEnScore);
        middleScoreList.add(middleEnScore);
        middleScoreList.add(middleEnScore);
        middleScoreList.add(middleEnScore);
        middleScoreList.add(middleEnScore);
        middleSchoolMap.put("itemList", middleScoreList);
        middleSchoolMap.put("size", middleScoreList.size());

        eduList.add(primarySchoolMap);
        eduList.add(middleSchoolMap);
        context.put("eduList", eduList);
        try(ServletOutputStream outputStream = response.getOutputStream()){
            PdfUtil.pdfFile(context, "static/demo.html", outputStream);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

6、调用接口浏览器预览

在这里插入图片描述

相关推荐

  1. qt绘制生成PDF文件

    2024-03-27 11:06:06       30 阅读
  2. android pdf框架-6,文本生成pdf

    2024-03-27 11:06:06       22 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-27 11:06:06       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-27 11:06:06       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-27 11:06:06       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-27 11:06:06       18 阅读

热门阅读

  1. 英语口语 3.27

    2024-03-27 11:06:06       18 阅读
  2. C++ Lists(链表)基本用法

    2024-03-27 11:06:06       17 阅读
  3. Github 2024-03-26 开源项目日报 Top10

    2024-03-27 11:06:06       16 阅读
  4. 检查文件是否为图片或者视频

    2024-03-27 11:06:06       17 阅读
  5. 智能媒体时代认知安全的关键资源

    2024-03-27 11:06:06       16 阅读
  6. [蓝桥杯 2015]机器人数目

    2024-03-27 11:06:06       17 阅读