我们经常在进行前后端设计的时候需要对前端下载请求进行相应,对响应报文进行封装成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>
六、实现效果