springboot配合Freemark模板生成word,前台vue接收并下载【步骤详解并奉上源码】

简介: springboot配合Freemark模板生成word,前台vue接收并下载【步骤详解并奉上源码】

前言

FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。

成果图:

从浏览器直接下载到本地

下载好的word文件 蓝色圈圈里的数据均为动态数据

注:这里可以自行写word模板

一、使用步骤

1.打开word模板,给需要赋值的位置先填上数据,方便查找编写freemarker代码,如下图

2.将word文件另存为xml文件 到桌面 ,然后修改jhj.xml修改后缀 改为 jhj.ftl 文件

1.刚打开的xml文件会比较长不太方便查看 可以把内容复制到菜鸟工具进行格式化 找到之前做好标记的位置 将数据替换

2.list循环数据 : 在<w:tr> 前加上 <#list taskstep as taskstep> ** </w:tr>在这之后加上结束标签 </#list>


二、后台代码

1.模板存放位置

2.依赖引入

    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml-schemas</artifactId>
        <version>3.9</version>
      </dependency>

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-freemarker</artifactId>
      </dependency>

3.后端代码

    @RequestMapping(value = "/Testrecord", method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<byte[]>   Testrecord(@RequestBody Map<String, Object> paras, HttpServletRequest request) throws Exception {
        String path = request.getServletContext().getRealPath("/");
        //设备信息  获取数据
        BaseResult<Map<String, Object>> DeviceTask= deviceModuleService.getOneDeviceTask((Integer) paras.get("id"));

        //测试条件 获取数据
  
        BaseResult<List<DeviceTaskStep>> deviceTaskStepByParas = deviceModuleService.getDeviceTaskStepByParas(paras);


        List<DeviceTaskStep> taskstep = deviceTaskStepByParas.getData();

//       循环方式
        BaseResult<List<DeviceTaskLoop>> deviceTaskLoopByParas = deviceModuleService.getDeviceTaskLoopByParas(paras);
        System.out.println(deviceTaskLoopByParas.getData().toString()+"SAD");
        List<DeviceTaskLoop> taskloop = deviceTaskLoopByParas.getData();
//        设备信息
        Map<String, Object> datataskstep = DeviceTask.getData();
        System.out.println(datataskstep);
        Object applyNo = datataskstep.get("reportNo");
        Configuration configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
        // 模板存放路径
        configuration.setClassForTemplateLoading(this.getClass(), "/template");
        // 获取模板文件
        Template template = configuration.getTemplate("Testrecord.ftl");
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        Map<String,Object> resultMap = new HashMap<>();
//        设备信息  
        resultMap.put("reportno",datataskstep.get("reportNo"));//word加入单数据
        resultMap.put("devicename",datataskstep.get("deviceName"));
        resultMap.put("manufacturer",datataskstep.get("manufacturer"));
        resultMap.put("basictypename",datataskstep.get("basicTypeName"));
        resultMap.put("devicecode",datataskstep.get("deviceCode"));

        System.out.println();
        if(datataskstep.get("startTime")==null){
            resultMap.put("starttime"," ");
        }else {
            resultMap.put("starttime",datataskstep.get("startTime"));
        }
        if(datataskstep.get("endTime")==null){
            resultMap.put("endtime"," ");
        }else {
            resultMap.put("endtime",datataskstep.get("endTime"));
        }


        // 测试条件
        List<Map<String, Object>> tasksteps = new ArrayList<Map<String, Object>>();
        if (taskstep.size()==0){
            Map<String, Object> map=new HashMap<String, Object>();
            map.put("stepNum"," ");
            map.put("temp",  " ");
            map.put("humid",  " ");
            map.put("timeHour",  " ");
            map.put("timeMin", " ");
            tasksteps.add(map);
        }else {
            for (int i = 0; i < taskstep.size(); i++) {
//
                Map<String, Object> map=new HashMap<String, Object>();
                map.put("stepNum", taskstep.get(i).getStepNum());
                map.put("temp",  taskstep.get(i).getTemp());
                map.put("humid",  taskstep.get(i).getHumid());
                map.put("timeHour",  taskstep.get(i).getTimeHour());
                map.put("timeMin",  taskstep.get(i).getTimeMin());
                tasksteps.add(map);
            }
        }



//        循环方式
        List<Map<String, Object>> taskloops = new ArrayList<Map<String, Object>>();
        //这里做一个判断  如果加入了空数据会报错
        if (taskloop.size()==0){
            Map<String, Object> map=new HashMap<String, Object>();
            map.put("loopNum", " ");
            map.put("stepStart", " ");
            map.put("stepStop", " ");
            map.put("loopCount",  " ");
            taskloops.add(map);
        }else {
            for (int i = 0; i < taskloop.size(); i++) {
//            System.out.println(taskloop.get(i).getTaskId()+"AAA");
                Map<String, Object> map=new HashMap<String, Object>();
                map.put("loopNum", taskloop.get(i).getLoopNum());
                map.put("stepStart",  taskloop.get(i).getStepStart());
                map.put("stepStop",  taskloop.get(i).getStepStop());
                map.put("loopCount",  taskloop.get(i).getLoopCount());
                taskloops.add(map);
            }
        }

    //word加入循环数据
        resultMap.put("taskstep",tasksteps);
        resultMap.put("taskloop",taskloops);
//        测试条件

        File outFile = new File(String.format("%s%s.%s",path,applyNo,"doc"));
        Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
        template.process(resultMap,out);
        out.flush();
        out.close();
        //这是是绝对路径
        // String path = "C:\\Users\\zhangyf\\";
        // String filename = "aaa.doc";
        String filename = String.format("%s.%s",applyNo,"doc");
        File file = new File(path+filename);
        HttpHeaders headers = new HttpHeaders();
        //下载显示的文件名,解决中文名称乱码问题
        String downloadFileName = new String(filename.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
        //通知浏览器以attachment(下载方式)打开图片
        headers.setContentDispositionFormData("attachment", downloadFileName);
        //application/octet-stream:二进制流数据(最常见的文件下载)
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        //201 HttpStatus.CREATED
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.CREATED);

    }

3.前端vue 浏览器下载代码

export function Testrecord(data) {
    return axios({
        url: '/h/deviceModule/Testrecord',
        method: 'post',
        data: data,
     responseType: 'blob' //这里改一下
    })
}


  // 导出测试结果模板
    hanldeExportTaskDoc(record) {
      const params = {
        id: record.id,
     taskId: record.id,
      }
   
   
      this.$api.Testrecord(params).then((res) => {
        if (res) {
       console.log(res);
     
  this.downloadWordFile(res,record.reportNo);
  }
      })
  
    },
  
  downloadWordFile (file,No) {
    console.log(No+'.docx');
    const blob = new Blob([file], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
  
    const url = URL.createObjectURL(blob)
    const a = document.createElement('A')
  
    a.download = No+'.docx'  //下载的文件名  自行设置
    a.href = url
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
  },
  
  

五、最后一步完成后 ,就是成果图的效果啦!

相关文章
|
9月前
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
892 1
|
5月前
|
前端开发 安全 Java
基于springboot+vue开发的会议预约管理系统
一个完整的会议预约管理系统,包含前端用户界面、管理后台和后端API服务。 ### 后端 - **框架**: Spring Boot 2.7.18 - **数据库**: MySQL 5.6+ - **ORM**: MyBatis Plus 3.5.3.1 - **安全**: Spring Security + JWT - **Java版本**: Java 11 ### 前端 - **框架**: Vue 3.3.4 - **UI组件**: Element Plus 2.3.8 - **构建工具**: Vite 4.4.5 - **状态管理**: Pinia 2.1.6 - **HTTP客户端
713 4
基于springboot+vue开发的会议预约管理系统
|
4月前
|
XML JSON Java
【SpringBoot(三)】从请求到响应再到视图解析与模板引擎,本文带你领悟SpringBoot请求接收全流程!
Springboot专栏第三章,从请求的接收到视图解析,再到thymeleaf模板引擎的使用! 本文带你领悟SpringBoot请求接收到渲染的使用全流程!
382 3
|
6月前
|
前端开发 JavaScript Java
基于springboot+vue开发的校园食堂评价系统【源码+sql+可运行】【50809】
本系统基于SpringBoot与Vue3开发,实现校园食堂评价功能。前台支持用户注册登录、食堂浏览、菜品查看及评价发布;后台提供食堂、菜品与评价管理模块,支持权限控制与数据维护。技术栈涵盖SpringBoot、MyBatisPlus、Vue3、ElementUI等,适配响应式布局,提供完整源码与数据库脚本,可直接运行部署。
368 6
基于springboot+vue开发的校园食堂评价系统【源码+sql+可运行】【50809】
|
7月前
|
人工智能 JSON Java
Spring Boot 如何接收并处理不确定类型的请求参数?
在 Spring Boot 中,当需要处理结构不确定的 JSON 数据时,可以使用 `Map` 类型灵活接收键值对数据。对于更复杂的场景,可通过 Jackson 注解支持多态类型、自定义反序列化器,或在接收后动态解析 JSON 数据,提升处理灵活性和扩展性。
243 0
|
8月前
|
机器学习/深度学习 数据采集 人机交互
springboot+redis互联网医院智能导诊系统源码,基于医疗大模型、知识图谱、人机交互方式实现
智能导诊系统基于医疗大模型、知识图谱与人机交互技术,解决患者“知症不知病”“挂错号”等问题。通过多模态交互(语音、文字、图片等)收集病情信息,结合医学知识图谱和深度推理,实现精准的科室推荐和分级诊疗引导。系统支持基于规则模板和数据模型两种开发原理:前者依赖人工设定症状-科室规则,后者通过机器学习或深度学习分析问诊数据。其特点包括快速病情收集、智能病症关联推理、最佳就医推荐、分级导流以及与院内平台联动,提升患者就诊效率和服务体验。技术架构采用 SpringBoot+Redis+MyBatis Plus+MySQL+RocketMQ,确保高效稳定运行。
638 0
|
7月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
1186 0
|
8月前
|
人工智能 Java 测试技术
Spring Boot 集成 JUnit 单元测试
本文介绍了在Spring Boot中使用JUnit 5进行单元测试的常用方法与技巧,包括添加依赖、编写测试类、使用@SpringBootTest参数、自动装配测试模块(如JSON、MVC、WebFlux、JDBC等),以及@MockBean和@SpyBean的应用。内容实用,适合Java开发者参考学习。
960 0
|
4月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
475 3
|
4月前
|
Java 测试技术 数据库连接
【SpringBoot(四)】还不懂文件上传?JUnit使用?本文带你了解SpringBoot的文件上传、异常处理、组件注入等知识!并且带你领悟JUnit单元测试的使用!
Spring专栏第四章,本文带你上手 SpringBoot 的文件上传、异常处理、组件注入等功能 并且为你演示Junit5的基础上手体验
1002 2