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)
  },
  
  

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

相关文章
|
17天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
95 62
|
15天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
34 2
|
18天前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
14天前
|
JavaScript NoSQL Java
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
29 0
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
143 1
|
2月前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的服装商城管理系统
基于Java+Springboot+Vue开发的服装商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的服装商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
147 2
基于Java+Springboot+Vue开发的服装商城管理系统
|
2月前
|
前端开发 JavaScript Java
SpringBoot项目部署打包好的React、Vue项目刷新报错404
本文讨论了在SpringBoot项目中部署React或Vue打包好的前端项目时,刷新页面导致404错误的问题,并提供了两种解决方案:一是在SpringBoot启动类中配置错误页面重定向到index.html,二是将前端路由改为hash模式以避免刷新问题。
229 1
|
2月前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的大学竞赛报名管理系统
基于Java+Springboot+Vue开发的大学竞赛报名管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的大学竞赛报名管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
218 3
基于Java+Springboot+Vue开发的大学竞赛报名管理系统
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用
【10月更文挑战第8天】本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,通过 Spring Initializr 创建并配置 Spring Boot 项目,实现后端 API 和安全配置。接着,使用 Ant Design Pro Vue 脚手架创建前端项目,配置动态路由和菜单,并创建相应的页面组件。最后,通过具体实践心得,分享了版本兼容性、安全性、性能调优等注意事项,帮助读者快速搭建高效且易维护的应用框架。
40 3
|
2月前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的蛋糕商城管理系统
基于Java+Springboot+Vue开发的蛋糕商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的蛋糕商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
142 3
基于Java+Springboot+Vue开发的蛋糕商城管理系统