使用Freemarker输出word文档到浏览器与本地
本期我们介绍如何使用Freemarker导出word文档?
项目需求如下:
前些时间开发人力资源项目,项目在正式上线之后,客户录入的大良人员基础信息,包括人员基础信息,教育经历,工作经历,培训经历与家庭情况,这些数据都是使用独立的表来存储的,后来客户反馈,说查看个人信息不方便,在人员调动时候还需要打印个人简历给领导看,特别提出导出个人简历功能
最后输出效果如下:
经过考虑: 有两种备选方案,第一种是使用itextPDF输出PDF文档,第二种是使用Freemarker导出word,但是在实际开发中发现,使用itextPDF在填充工作经历等信息时候需要用到循环,而itextPDF对循环支持的不是很友好,于是果断时候了Freemarker
使用模板引擎至少需要四步走:
1.定义模板引擎
2.创建数据模型
3.填充数据到模板中
4.输出文档
1.首先定义模板
1.1 创建word文档,定义个人简历模板,效果如下:
1.2另存为XML文件
使用文本编辑器打开
1.3定义插值
我们使用文本编辑器打开之后会有一些乱,可以使用代码在线格式化工具格式化一下,地址https://tool.oschina.net/codeformat/xml
我们根据word模板搜索姓名,找到‘5’,并替换为插值表达式
个人基础信息全部使用以上方式替换
工作经历教育经历等需要使用循环:
搜索工作经历:找到<w:tr>标签,除标题之外只保留一个,每一个<w:tr>代表为一行数据
注意
<#list workList as work>
</#list>
workList 是数据源,as 表示循环 work 代表每次循环的对象
教育经历,家庭信息同理
处理完成后,修改后缀名为.ftl,放到项目templates目录下
2.代码开始
2.1、引入依赖
<!--PDF常用工具类 -->
- <dependency>
- <groupId>com.itextpdf</groupId>
- <artifactId>itextpdf</artifactId>
- <version>2.3.28</version>
- </dependency>
/**
* 下载个人简历word文档
* @param response
* @param userId
* @throws IOException
* @throws TemplateException
*/
@GetMapping("/parint1/{userId}")
@ResponseBody
public void print(HttpServletResponse response,@PathVariable("userId") String userId) throws IOException, Exception {
Long userId1 = Long.valueOf(userId);
HrStaffInfo staffInfo = hrStaffInfoService.selectHrStaffInfoById(userId1);
String content = exportFile(staffInfo);
InputStream inputStream = IOUtils.toInputStream(content);
ServletOutputStream out = null;
try {
//输出文件
response.setHeader("content-type", "application/octet-stream");
response.setContentType("application/octet-stream;charset=UTF-8");
//response.setHeader("Content-Disposition", "attachment;filename=" + "aaa企业在编在职人员情况登记表bb"+".doc");
response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(staffInfo.getUserName()+"-顺德区区属国有企业在编在职人员情况登记表", "UTF-8")+ ".doc")));
out = response.getOutputStream();
byte[] buffer = new byte[1024]; // 缓冲区
int bytesToRead = -1;
// 通过循环将读入的Word文件的内容输出到浏览器中
while((bytesToRead = inputStream.read(buffer)) != -1) {
out.write(buffer, 0, bytesToRead);
}
}catch (Exception e){
log.error("导出Excel异常{}", e.getMessage());
throw new BusinessException("导出word失败,请联系网站管理员!");
}finally {
out.flush();
out.close();
inputStream.close();
}
}
public String exportFile(HrStaffInfo staffInfo ) throws Exception{
HrStaffEducation education1 = new HrStaffEducation();
HrStaffWork hrStaffWork = new HrStaffWork();
HrStaffTrain hrStaffTrain = new HrStaffTrain();
HrStaffFamily hrStaffFamily = new HrStaffFamily();
education1.setStaffInfoId(staffInfo.getUserId());
hrStaffWork.setStaffInfoId(staffInfo.getUserId());
hrStaffTrain.setStaffInfoId(staffInfo.getUserId());
hrStaffFamily.setStaffInfoId(staffInfo.getUserId());
List<HrStaffEducation> educationList = educationService.selectHrStaffEducationList(education1);
SysDictData dictData2 = new SysDictData();
dictData2.setDictType("hr_staff_degree");
List<SysDictData> eduList = dictDataService.selectDictDataList(dictData2);
for (HrStaffEducation hrStaffEducation : educationList) {
String degree = hrStaffEducation.getDegree();
if(degree == null){
continue;
}
for (SysDictData dictData : eduList) {
if(degree.equals(dictData.getDictValue())){
hrStaffEducation.setDegree(dictData.getDictLabel());
continue;
}
}
continue;
}
//查询工作经历
List<HrStaffWork> workList = workService.selectHrStaffWorkList(hrStaffWork);
//查询培训经历
List<HrStaffTrain> trainList = trainService.selectHrStaffTrainList(hrStaffTrain);
//查询家庭情况
List<HrStaffFamily> familyList = familyService.selectHrStaffFamilyList(hrStaffFamily);
//创建配置类
Configuration configuration = new Configuration(Configuration.getVersion());
String classPath = this.getClass().getResource("/").getPath();
configuration.setDirectoryForTemplateLoading(new File(classPath+"templates/"));
//获取模板文件
Template template = configuration.getTemplate("curriculum_vitae.ftl");
Map<String, Object> data = new HashMap<String, Object>();
Long companyId = staffInfo.getCompanyId();
String companyName = hrOrgCompanyService.selectHrOrgCompanyById(companyId).getDeptName();
data.put("companyName", companyName);
Calendar cal = Calendar.getInstance();
String model="yyyy-MM-dd"; //指定格式化的模板
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(model);
String date = simpleDateFormat.format(new Date());
String[] split = date.split("-");
data.put("year", split[0]);
data.put("month", split[1]);
data.put("day", split[2]);
//-------------------------------------------------------------
SysDictData dictData = new SysDictData();
List<SysDictData> sexList = dictDataService.selectDictDataList(dictData);
String sex = "";
String national = "";
String highestDegree = "";
String partHighestDegree = "";
// String national = "";
// String national = "";
for (SysDictData sysDictData : sexList) {
if (staffInfo.getSex()!= null && staffInfo.getSex().equals(sysDictData.getDictValue())&&"sys_user_sex".equals(sysDictData.getDictType())){
sex = sysDictData.getDictLabel();
}
if ( staffInfo.getNational()!= null && staffInfo.getNational().equals(sysDictData.getDictValue())&&"hr_staff_national".equals(sysDictData.getDictType())){
national = sysDictData.getDictLabel();
}
if (staffInfo.getHighestDegree()!= null && staffInfo.getHighestDegree().equals(sysDictData.getDictValue())&&"hr_staff_qualification".equals(sysDictData.getDictType())){
highestDegree = sysDictData.getDictLabel();
}
if (staffInfo.getPartHighestDegree() != null && staffInfo.getPartHighestDegree().equals(sysDictData.getDictValue())&&"hr_staff_qualification".equals(sysDictData.getDictType())){
partHighestDegree = sysDictData.getDictLabel();
}
}
//-------------------------------------------------------------
String deptName = hrOrgCompanyService.selectHrOrgCompanyById(staffInfo.getDeptId()).getDeptName();
//-------------------------------------------------------------
data.put("userName", staffInfo.getUserName()); //5
data.put("sex", sex); //7
data.put("bornYear", staffInfo.getBornYear()); //8
data.put("bornMonth", staffInfo.getBornMonth()); //8
data.put("nativePlace", staffInfo.getNativePlace()); //9
data.put("national", national); //10
data.put("idNumber", staffInfo.getIdNumber()); //11
data.put("partyTime", staffInfo.getPartyTime()); //12
data.put("workTime", staffInfo.getWorkTime()); //13
data.put("birthPlace", staffInfo.getBirthPlace()); //14
data.put("registeredPlace", staffInfo.getRegisteredPlace()); //15
data.put("highestDegree", highestDegree); //16
data.put("highestProfessional", staffInfo.getHighestProfessional()); //17
data.put("graduateSchool", staffInfo.getGraduateSchool()); //18
data.put("partHighestDegree", partHighestDegree); //19
data.put("partHighestProfessional", staffInfo.getPartHighestProfessional()); //20
data.put("partGraduateSchool", staffInfo.getPartGraduateSchool()); //21
data.put("professionalQualifications", staffInfo.getProfessionalQualifications()); //22
data.put("maritalStatus", staffInfo.getMaritalStatus()); //22
data.put("unitTime", staffInfo.getUnitTime()); //25
data.put("positionName", staffInfo.getPositionName()); //26
data.put("dept", deptName); //27
data.put("currentAddress", staffInfo.getCurrentAddress()); //28
data.put("phoneNumber", staffInfo.getPhonenumber()); //29
//-------------------------------------------------------------
// data.put("staffInfo",staffInfo);
//要和模板中定义的变量名保持一致
data.put("educationList",educationList);
data.put("workList",workList);
data.put("trainList",trainList);
data.put("familyList",familyList);
String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
return content;
}
定义前端接收请求:
/**
* 下载word文档
*/
function print1() {
window.location.href = ctx + "hr/hrStaffInfo/parint1/" + userId;
}
如果你想输出到本地
定义输出路径即可,其他代码与输出到浏览器保持一致
@GetMapping("/export/{userId}")
@ResponseBody
public TableDataInfo list(@PathVariable("userId") Long userId, HttpServletResponse response) throws Exception {
HrStaffInfo staffInfo = hrStaffInfoService.selectHrStaffInfoById(userId);
String content = exportFile(staffInfo);
try {
InputStream inputStream1 = IOUtils.toInputStream(content);
//定义输出路径即可,其他代码与输出到浏览器保持一致
FileOutputStream fileOutputStream = new FileOutputStream(new File("d:/test1.doc"));
int copy = IOUtils.copy(inputStream1, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
inputStream1.close();
} catch (Exception e) {
logger.error("下载个人档案异常", e);
throw new BaseException("下载个人档案异常");
}
好了今天的代码就到这里了,如有不明白之处欢迎留言。
上一篇: 16.网页的定位练习
下一篇: 买了本COBOL的书