springboot根据模板导出word_菜鸟的传奇人生的博客-程序员秘密

技术标签: spring  java  java后端  

我们经常在进行前后端设计的时候需要对前端下载请求进行相应,对响应报文进行封装成word供下载,下面基于springboot对这一过程进行介绍

一、准备word模板,用于设置导出时的样式

模板

二、pom.xml文件中引入依赖

   <dependency>
        <groupId>cn.afterturn</groupId>
        <artifactId>easypoi-base</artifactId>
        <version>3.0.3</version>
    </dependency>
    <dependency>
        <groupId>cn.afterturn</groupId>
        <artifactId>easypoi-web</artifactId>
        <version>3.0.3</version>
    </dependency>
    <dependency>
        <groupId>cn.afterturn</groupId>
        <artifactId>easypoi-annotation</artifactId>
        <version>3.0.3</version>
    </dependency>

三、构造ExportWord类

package com.zju.gcs.common.util;

import cn.afterturn.easypoi.word.WordExportUtil;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Map;
public class ExportWord {
    /**
     * 导出word
     * <p>第一步生成替换后的word文件,只支持docx</p>
     * <p>第二步下载生成的文件</p>
     * <p>第三步删除生成的临时文件</p>
     * 模版变量中变量格式:{
   {foo}}
     * @param templatePath word模板地址
     * @param temDir 生成临时文件存放地址
     * @param fileName 文件名
     * @param params 替换的参数
     * @param request HttpServletRequest
     * @param response HttpServletResponse
     */
    public static void exportWord(String templatePath, String temDir, String fileName, Map<String, Object> params, HttpServletRequest request, HttpServletResponse response) {
        Assert.notNull(templatePath,"模板路径不能为空");
        Assert.notNull(temDir,"临时文件路径不能为空");
        Assert.notNull(fileName,"导出文件名不能为空");
        Assert.isTrue(fileName.endsWith(".docx"),"word导出请使用docx格式");
        if (!temDir.endsWith("/")){
            temDir = temDir + File.separator;
        }
        File dir = new File(temDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        try {
            String userAgent = request.getHeader("user-agent").toLowerCase();
            if (userAgent.contains("msie") || userAgent.contains("like gecko")) {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } else {
                fileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1");
            }
            XWPFDocument doc = WordExportUtil.exportWord07(templatePath, params);
            String tmpPath = temDir + fileName;
            FileOutputStream fos = new FileOutputStream(tmpPath);
            doc.write(fos);
            // 设置强制下载不打开
            response.setContentType("application/force-download");
            // 设置文件名
            response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
            OutputStream out = response.getOutputStream();
            doc.write(out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            delFileWord(temDir,fileName);//这一步看具体需求,要不要删
        }
    }
    /**
     * 删除零时生成的文件
     */
    public static void delFileWord(String filePath, String fileName){
        File file =new File(filePath+fileName);
        File file1 =new File(filePath);
        file.delete();
        file1.delete();
    }
}

这时候如果显示httpserveltrequest报错,则还需要在当前模块的配置文件下引入依赖

<dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>

三、controller层,接收前端请求

 @RequestMapping("/download")
    public void downloadMedicalRecord( HttpServletRequest request, HttpServletResponse response) {
        try {
            medicalRecordService.downloadMedicalRecord(1,request,response);
        } catch (Exception e) { }
    }

引用service层的download方法进行请求的处理,并捕捉异常

四、service 层

声明接口函数

void downloadMedicalRecord(Integer id, HttpServletRequest request, HttpServletResponse response) throws IllegalAccessException, IOException;
}

五、service实现层

@Override
    public void downloadMedicalRecord(Integer id,HttpServletRequest request, HttpServletResponse response){
        MedicalRecordDOWithBLOBs record = medicalRecordDOMapper.selectByPrimaryKey(id);
        SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd");
        Map<String,Object> params = new HashMap<>();
        params.put("patientId",record.getPatientId() == null ? "暂无": record.getPatientId());
        params.put("name",record.getName() == null ? "暂无": record.getName());
        System.out.println(1);
        params.put("gender",record.getGender()==1? "男":"女");
        params.put("doctorName",record.getDoctorName() == null ? "暂无": record.getDoctorName());
        params.put("birthday", record.getBirthday() == null ? "暂无": dateFormat.format(record.getBirthday()));
        params.put("height",record.getHeight() == null ? "暂无": record.getHeight());
        params.put("weight",record.getWeight() == null ? "暂无": record.getWeight());
        params.put("disease",record.getDisease() == null ? "暂无": record.getDisease());
        params.put("chfCmp",record.getChfCmp() == null ? "暂无": record.getChfCmp());
        params.put("hisPreIll",record.getHisPreIll() == null ? "暂无": record.getHisPreIll());
        params.put("hisTre",record.getHisTre() == null ? "": record.getHisTre());
        params.put("prvMedHis",record.getPrvMedHis() == null ? "暂无": record.getPrvMedHis());
        params.put("perHis",record.getPerHis() == null ? "暂无": record.getPerHis());
        params.put("famHis",record.getFamHis() == null ? "暂无": record.getFamHis());
        params.put("treAdv",record.getTreAdv() == null ? "暂无": record.getTreAdv());

        ExportWord.exportWord("C:/Users/23644/Desktop/export.docx","test","第"+id+"份电子病历.docx",params,request,response);
    }

上面MedicalRecordDOWithBLOBs为接收数据库数据定义的一个接收类,可根据实际情况自定义
selectByPrimaryKey用于查询数据库相关数据

<select id="selectByPrimaryKey" resultMap="ResultMapWithBLOBs" parameterType="java.lang.Integer" >
    select m.id, m.patient_id, m.name, d.name as doctor_name, m.gender, m.birthday, m.weight, m.height,
    m.disease, m.chf_cmp, m.his_pre_ill, m.his_tre, m.prv_med_his, m.per_his, m.fam_his, m.tre_adv
    from medical_record m
    left join doctor d
    on m.doctor_id = d.id
    where m.id = #{id}
  </select>

六、实现效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_40820235/article/details/105005593

智能推荐

android 8.0 Autofill Framework (自动填充框架)_weixin_33872660的博客-程序员秘密

android 8 时 增加了一个自动填充框架,它是可以是我们在填写表单是更加容易减少出错,还可以我们减少填写表单的时间,填写表单是一项耗时且容易出错的任务,用户可能很容易对需要这些类型任务的应用感到沮丧,自动填充框架通过提供以下优势来改善用户体验:更少的时间用于填充字段 自动填充功能可以帮助用户避免重新输入信息最大限度地减少用户输入错误 打字很容易出错,特别是在移动设备中删除输入信息的必要...

创建恶意无线热点--Mdk3_mdk3伪造热点_小人物哎的博客-程序员秘密

kali的一个工具--mdk3mdk3 &quot;网卡&quot; b -n &quot;wifi名称&quot; -c 1 -s 200 -a例:mdk3 wlan0 b -n test -c 1 -s 200 -ab beacon泛洪攻击-f 指定wifi名称的文件夹-n 加上wifi名称-w Fake WEP encrypted stations 设置假的加密wep-g Fake 802.11b stations (54 Mbi...

Unity如何直接获取深度缓冲_unity复制深度缓冲_UWA的博客-程序员秘密

1)Unity如何直接获取深度缓冲​2)Unity Editor下SpriteAtlas加载的问题3)无法将GameObject从Project窗口拖拽到SceneView窗口4)UGUI的事件响应问题5)iOS设置Texture2D的mipMapBias无效这是第247篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。UWA 问答社区:answer.uwa4d.comUWA QQ群2:793972859(原群已满员)

linux各大发行版本_weixin_33709219的博客-程序员秘密

linux各大版本:Debian 这个发行版本在所有发行版本里面堪称最严谨的,apt软件包管理机制可以让用户快速建立起来高效的操作系统。稳定性也是出名的,这个发行版很多软件默认就有很好的设置,可以作为日常的工作使用。对硬件支持也不错,笔者的笔记本上外设特别多,几乎没有做什么特别的设置那些外设就完全正常的工作了,当然中文化可能需要花你一点点的时间,也就是添加几句话而已...

新版Chrome谷歌浏览器设置网页编码格式_chrome mac 编码格式_仲夏宁叶香的博客-程序员秘密

新版谷歌浏览器更新后取消了设置里的编码格式的设定,改为自动识别,但是还是有一些网站查看源代码时中文乱码,我们只需要下载一个插件就可以设置网页编码格式谷歌浏览器里隐藏着谷歌应用店,打开谷歌浏览器,设置里找到Chrome网上应用店,点击进入(需要开VPN):在Chrome 网上应用店 里搜:Charset 添加此插件即可然后可以在插件里修改当前网页的编码格式了...

AI视频抠图换背景,无需「绿幕」,也可达到影视级效果_jiumillion的博客-程序员秘密

牛学长智能抠图工具是一款专业的视频抠像工具,可以AI自动识别扣除人像视频背景,无需手动扣除。基于深度学习的视频抠图算法,可以精细到每一根发丝。智能识别抠除区域,省时省力,快速获得带透明背景或绿幕的视频

随便推点

Oracle EM 无法连接_cmiufchzxbjf932905的博客-程序员秘密

闲着无聊,搞搞数据库EM。net start oracleserviceorcl后,手动把相关的服务启动了一下。然后用HTTP连接EM,竟然无法连接。想来我也没改IP啊,这是我的个人PC。在看了下服务,嘿~ 原来oracleDB...

WCF初探_amclap的博客-程序员秘密

WCF宿主与服务托管若要公开WCF服务,需要提供一个运行服务的宿主环境。就像.NET CLR需要创建宿主环境以托管代码一般,WCF的宿主环境同样运行在进程的应用程序域中。在应用程序域中可以创建一个或多个ServiceHost实例,其关系如图一所示: 图一  托管ServiceHostWCF并不推荐在应用程序域中创建多个ServiceHost实例。如果要托管多个服务,完全可以在一个宿主中通过多个

【Android应用开发】-(17)获取Google天气预报通过Xml和JSON解析数据_android 获取国外天气_tangcheng_ok的博客-程序员秘密

最近在做一个天气预报的Widget,通过google提供的api可以查询全世界的天气情况,这篇文章主要讲述如何通过Android的JSON获取城市的经纬度,程序很简单。稍后我将demo供来此博客的朋友。废话少说,且看下文:    设计如下:通过JsonDemoActivity输入国家简称,跳转到CityListActivity(用来显示城市列表),点击需要查询城市返回天气信息。在JsonDemoA

Java程序员顺利拿到阿里offer,这些面试题你能掌握多少?_chengyi5916的博客-程序员秘密

从7月分开始,打算找工作,一个偶然的机会,拉勾上一个蚂蚁金服的师兄找到我,说要内推,在此感谢姚师兄,然后就开始了蚂蚁金服的面试之旅。把简历发过去之后,就收到了邮件通知,10个工作日联系我,请耐心等待。 阿里一面 没过2天就接到一个杭州的座机,说要约我进行电话面试,效率还是挺高,然后当天...

ISSP使用详细步骤_可爱包的博客-程序员秘密

关于片上调试工具ISSP板级仿真ISSP全称为系统内的源和探针在将ISSP IP核添加工程并例化后,进行全编译、将sof文件下载到板上,打开tool中的ISSP工具,界面如下图1:1.source:顾名思义,相当于信号源,向模块写入数据。source中的数据作为输入,是可编辑的,首先选中需要编辑的对象,如上图(图标由灰色变为蓝色后),采用下图操作,改变数据格式为16进制,输入数据47ff,系统自动转为47ff h,之后点击最上面的“write source data”按钮,就成功写入了数据。

黑马程序员---基本数据类型对象包装类_Lola的笔记的博客-程序员秘密

---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ---------------------- 基本数据类型                        引用数据类型byte                                           Byteshort                 

推荐文章

热门文章

相关标签