使用freemarker插件,在浏览器生成word并提供下载

  • 欢使用freemarker生成复杂的word
    • 1.使用freemarker需要注意的点
    • 2.freemarker自动生成并下载到本地的word模板
    • 3.使用freemarker的步骤
    • 4.后台的代码
    • 5.总结

欢使用freemarker生成复杂的word

在开发中总会有很需求,当然导出word也很常用,接下来就看一下是如何在html生成的word。

1.使用freemarker需要注意的点

  1. 对于刚接触Freemarker得人来说,不用太深入了解freemarker,但是要知道基本使用的xml的标签有哪些,可以再循环list集合中更快速,更准备的找到对数据进行处理的位置,根据个人情况对数据进行快速处理。
(1)<w:t>:字符串,输入的文字内容
(2)<w:r>:表示行
(3)<w:p>:表示段落
(4)<w:tbl>:表示一个form表单
  1. 对于复杂的word,可能一个word文档中有很多的东西需要展示,可能是一个对象,可能是一个集合,也可能有很多的图片等,所以最基本常用的指令我们也应该知道,知道他的写法规范。
(1)<#if>    ‘内容’<#elseif>    ‘内容’<#else>    ‘内容’</#if>(2)<#list dataList as item></#list>
注:list为固定写法,dataList 为传过来的集合数据,对集合进行遍历,as相当于分配,item为遍历出的每个对象。

2.freemarker自动生成并下载到本地的word模板

3.使用freemarker的步骤

(1)首先我们要把想生成的模板中对应的数据使用** ${}**表示出来,如果有先要显示的图片我们就要把带图片的部分用一个图片把位置站出来,随意找来一张图片就可以。
如下图


(2)将处理好的word文档保存成xml文件格式
如下图

(3)将保存好的xml文件使用工具打开,我使用的是Nodepad++,打开后使用xml在线转换工具格式化,并替换Nodepad++中的内容

xml在线格式化工具

如下图


(3)接下来我们就需要手动去更改一些配置,在xml转化的过程中会出现同一个数据被拆分成多个数据,这里我们就需要把数据整合成一个整体,否则freemarker识别不出来,并且对需要一些内容进行遍历
如下图:
整合数据



list的遍历

if的使用,遍历图片

最后一步,将xml文件更改为后缀为.ftl的文件

4.后台的代码

(1)实体类
注意:get和set方法自己加

*** 项目组成员信息实体类*/
public class ProjectTeam implements Serializable {private static final long serialVersionUID = 1L;/*** 项目组专业*/private String projectSpeciality;/*** 项目组负责人字样模板*/private String ownerName;/*** 项目组参与人字样模板*/private String participantsName;/*** 项目组负责人*/private String owner;/*** 参与人员*/private String personName;}
/*** 项目类别封装信息对象实体类*/
public class ProjectTemplate implements Serializable {private static final long serialVersionUID = 1L;/*** 专业类别等级*/private String typeLevel;/*** 说明*/private String describ;/*** 本项目类别标志(是:1/否:0)*/private int typeFlag;}
/*** 本项目类别实体类*/
public class ProjectType implements Serializable {private static final long serialVersionUID = 1L;/*** 本专业类型具体数据(type+rank)*/private String projectType;/*** 本专业类型*/private String speciality;}
/*** 任务书表头信息实体类*/
public class TaskBook implements Serializable {private static final long serialVersionUID = 1L;/*** 项目名称*/private String proName;/*** 责任部门*/private String deptId;/*** 责任单位*/private String officeId;/*** 生效日期*/private String generateDate;/*** 版本*/private String version;/*** 文件编号*/private String bookNo;/*** 项目来源*/private String proSource;/*** 项目类别标志(订单,自研,专项)*/private String orderFlag;/*** 年份*/private int year;/*** 图片*/private List<String> photo;}
/***项目类别专业类别信息*/
public class TypeSpeciality  implements Serializable {private static final long serialVersionUID = 1L;/*** 项目列别专业*/private String speciality;/*** 项目类别封装信息对象实体类集合*/private List<ProjectTemplate> projectTemplateList;}

(2)工具类
注意:模板文件放在/resource/template路径下

    private static final String ENCODING = "UTF-8";//注册配置private static Configuration configure = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);//功能描述:初始化configrationstatic{//设置编码和国家,否则会出现乱码configure.setEncoding(Locale.getDefault(),ENCODING);//加载模板文件,flt文件的存放路径,相对路径法configure.setClassForTemplateLoading(FreemarkerUtil.class, "/template");//设置异常处理器configure.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);}/*** 获取模板对象** @param templateFileName 模板名字*/public static Template getTemplate(String templateFileName) throws IOException {return configure.getTemplate(templateFileName, ENCODING);}

(3)控制层
注意:@ApiOperation和@SysLog都是swagger的注解,用不到可忽略

 /*** 下载Word任务书*/@ApiOperation(value = "下载Word任务书", notes = "下载Word任务书")@GetMapping("/downloadWord")@SysLog(value = "下载Word任务书", response = false)public void downloadWord(HttpServletResponse response){baseService.downloadWord(response);}

(4)业务层接口

   /*** 根据任务书模板导出word形式任务书**/String exportWordToAssignment();/*** 下载任务书word文档* @param response*/void downloadWord(HttpServletResponse response);

(5)业务层实现类

@Overridepublic String exportWordToAssignment() {//图片加载,获取base64码String imageBase1 = getImageBase("plm.jpg");String imageBase2 = getImageBase("cj.jpg");String imageBase3 = getImageBase("ps.jpg");List<String> photoList = new ArrayList<>();photoList.add(imageBase1);photoList.add(imageBase2);photoList.add(imageBase3);//第一个数据集合//封装任务书头信息String proName = "胖了吗";String version = "version1.0";Map<String, Object> map = new HashMap<String, Object>();TaskBook taskBook = new TaskBook();taskBook.setProName(proName);taskBook.setProSource("国外来源,今天是个好日子,全国进货");taskBook.setOrderFlag("自研");taskBook.setBookNo("NY00001");taskBook.setDeptId("软件研发");taskBook.setOfficeId("研发0001");taskBook.setVersion(version);taskBook.setPhotos(photoList);SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd");Date date = new Date();String format = ft.format(date);taskBook.setGenerateDate(format);Calendar cal = Calendar.getInstance();taskBook.setYear(cal.get(Calendar.YEAR));//数据放入map集合map.put("taskBook", taskBook);//第二个数据集合//外卖类别(数据测试数据总集合)--具体物品集合List<TypeSpeciality> typeSpecialityList = new ArrayList<>();//外卖类别(数据一)List<ProjectTemplate> projectTemplateList1 = new ArrayList<>();TypeSpeciality typeSpeciality1 = new TypeSpeciality();typeSpeciality1.setSpeciality("点心");for (int i = 1; i <6 ; i++) {ProjectTemplate projectTemplate = new ProjectTemplate();projectTemplate.setTypeLevel("点心"+i);projectTemplate.setDescrib("香喷喷的点心出锅了"+i);if(i==2){projectTemplate.setTypeFlag(1);}else{projectTemplate.setTypeFlag(0);}projectTemplateList1.add(projectTemplate);}//外卖类别(数据二)List<ProjectTemplate> projectTemplateList2 = new ArrayList<>();TypeSpeciality typeSpeciality2 = new TypeSpeciality();typeSpeciality2.setSpeciality("水果");for (int i = 1; i <6 ; i++) {ProjectTemplate projectTemplate = new ProjectTemplate();projectTemplate.setTypeLevel("水果"+i);projectTemplate.setDescrib("进口的水果可甜可甜了"+i);if(i==4){projectTemplate.setTypeFlag(1);}else{projectTemplate.setTypeFlag(0);}projectTemplateList2.add(projectTemplate);}//外卖类别(数据三)List<ProjectTemplate> projectTemplateList3 = new ArrayList<>();TypeSpeciality typeSpeciality3 = new TypeSpeciality();typeSpeciality3.setSpeciality("饮品");for (int i = 1; i <6 ; i++) {ProjectTemplate projectTemplate = new ProjectTemplate();projectTemplate.setTypeLevel("饮品"+i);projectTemplate.setDescrib("独家秘制黑暗料理果汁"+i);if(i==1){projectTemplate.setTypeFlag(1);}else{projectTemplate.setTypeFlag(0);}projectTemplateList3.add(projectTemplate);}//存入数据typeSpecialityList.add(typeSpeciality1);typeSpecialityList.add(typeSpeciality2);typeSpecialityList.add(typeSpeciality3);//数据放入map集合map.put("typeSpecialityList", typeSpecialityList);//第二个数据集合//根据任务书id,查询项目组成员//数据一List<List<ProjectTeam>> projectTeamAllList = new ArrayList<>();List<ProjectTeam> proList1 = new ArrayList<>();ProjectTeam projectTeam1 = new ProjectTeam();projectTeam1.setProjectSpeciality(typeSpeciality1.getSpeciality());projectTeam1.setOwnerName("负责人");projectTeam1.setParticipantsName("执行人");projectTeam1.setOwner("王猛");projectTeam1.setPersonName("张志忠/马冬梅/郭琪");proList1.add(projectTeam1);projectTeamAllList.add(proList1);//数据二List<ProjectTeam> proList2 = new ArrayList<>();ProjectTeam projectTeam2 = new ProjectTeam();projectTeam2.setProjectSpeciality(typeSpeciality2.getSpeciality());projectTeam2.setOwnerName("负责人");projectTeam2.setParticipantsName("执行人");projectTeam2.setOwner("丘处机");projectTeam2.setPersonName("李思琪/田国胜/刘志丹");proList2.add(projectTeam2);projectTeamAllList.add(proList2);//数据三List<ProjectTeam> proList3 = new ArrayList<>();ProjectTeam projectTeam3 = new ProjectTeam();projectTeam3.setProjectSpeciality(typeSpeciality3.getSpeciality());projectTeam3.setOwnerName("负责人");projectTeam3.setParticipantsName("执行人");projectTeam3.setOwner("杨丽莎");projectTeam3.setPersonName("刘琴/张凯迪/李建东");proList3.add(projectTeam3);projectTeamAllList.add(proList3);//数据放入map集合map.put("projectTeamAllList", projectTeamAllList);//加载模板Template template = null;String content = null;try {template = getTemplate("任务书模板.ftl");content = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);} catch (IOException e) {e.printStackTrace();} catch (TemplateException e) {e.printStackTrace();}return content;}
@Overridepublic void downloadWord(HttpServletResponse response){//封装任务书头信息String proName = "胖了吗";String version = "version1.0";String saveFilePath =  proName +  version ;//查询返回的内容String content = exportWordToAssignment();//创建输入流读取InputStream inputStream =  null;//创建输出流ServletOutputStream out = null;try{inputStream =  IOUtils.toInputStream(content, "utf-8");//设置response的编码方式response.setHeader("content-type", "application/octet-stream");response.setContentType("application/octet-stream;charset=UTF-8");//设置附件文件名response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(saveFilePath, "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){throw new RuntimeException("导出Word任务书失败!,请联系维护人员");}finally {try {out.close();inputStream.close();} catch (IOException e) {e.printStackTrace();}}}
 /*** 获得图片的base64码,传入图片需要使用该方法把图片* 转成base64码放到数据集合中用于前台解析* @param src 路径*/public String getImageBase(String src) throws Exception {if (src == null || src == "") {return "";}File file = new File(src);if (!file.exists()) {return "";}InputStream in = null;byte[] data = null;try {in = new FileInputStream(file);data = new byte[in.available()];in.read(data);in.close();} catch (IOException e) {e.printStackTrace();}BASE64Encoder encoder = new BASE64Encoder();return encoder.encode(data);}

5.总结

此时我们的方法启动就可以使用了,在前台接受我们返回的response就可下载我们的word。

图片需要转化,我们要生成的数据要是用表达式占位。

使用freemarker插件,在浏览器生成word并提供下载相关推荐

  1. Java项目中利用Freemarker模板引擎导出--生成Word文档

    应邀写的一篇文章:Java项目中利用Freemarker模板引擎导出--生成Word文档 资源下载:https://download.csdn.net/download/weixin_41367523 ...

  2. Freemarker - 根据模板动态生成word文档

    文章目录 Freemarker 根据模板动态生成word文档 Freemarker 介绍: Freemarker 使用: freemarker加载模板目录的方法 参考资料 Freemarker 根据模 ...

  3. 帝国cms把网站文章内容生成word文档下载插件

    帝国cms把网站文章内容生成word文档下载插件 插件介绍 jQuery Word Export是一款可以将网页中的文字导出到微软Word文档中的jQuery插件.它通过FileSaver.js文件来 ...

  4. java 调用word插件_java一键生成word操作,比poi简单

    [Java] 纯文本查看 复制代码package com.jeeplus.modules.fact.util; import java.io.BufferedInputStream; import j ...

  5. Java使用FreeMarker模版技术动态生成word实践

    一.序言 在日常开发中,常常有动态word文件生成的需求,通过编制模版,然后动态修改word内容以组合成新的文件.报告单.请假单.发票页等都可以使用动态生成word来解决. 笔者总结归纳出通用技术要点 ...

  6. 根据模板生成word文档下载

    需求:根据数据库已有字段,填入写好的word并下载 工具 :freemark   一种方便生成word的引擎,内置好大量基础方法 思路: 一.将数据库数据按需求(根据id,根据name......)提 ...

  7. SpringCloud之利用FTL生成Word报表并下载

    1.首先,新建一个word文档:里面写需要下载的东西 2.编辑完后,另存为xml格式(不用管xml里面是什么),然后将后缀名xml改为ftl 3.这个ftl就是在Java代码中可生成word的模板文件 ...

  8. 纯前端vue利用docxtemplater实现生成word文档下载 word模板,勾选框的默认勾选。。

    首先需要下载如下工具: cnpm i docxtemplater pizzip jszip-utils file-saver -S 然后将它们引入: import JSZipUtils from &q ...

  9. 一款可以帮助你处理文字、编写内容等办公软件-Word 2013 提供下载

    Word文档官方下载免费版是Microsoft公司开发的Office2013办公组件之一,Word2013软件可以帮助你处理文字.编写内容等,不仅操作简单便捷,功能也是很实用,轻轻松完成文章的编辑处理 ...

最新文章

  1. 压缩机html200a功率,汽车空调功率有多大?如果用电瓶充电器供电能行吗?
  2. OpenGL天空游戏
  3. jQuery 重置/reset()表单
  4. 【随机过程】随机过程之泊松过程的推广
  5. TensorFlow 调用预训练好的模型—— Python 实现
  6. springboot-vue简单小项目搭建
  7. dtree 无法出现横向滚动条 (clip)
  8. Mybatis 动态传sql可以查询表名,任意表名,不固定字段的个数返回未定义的类型以及增删改...
  9. php 获取实例的类名,PHP类名获取方式及单例模式实现
  10. 曾辉机器人_奋进者曾辉:在润物无声中深植教育初心
  11. HTML5 20180918
  12. “绿坝-花季护航”软件
  13. java drawline变黑,为什么java.awt.Graphics.drawLine特别慢?
  14. Electron+Vue3+TypeScript+Vite桌面应用程序项目初始化
  15. 控制面板音频设置里显示“没有音频设备”,没有声音的解决办法
  16. Git基础(18):如何使用GitLab
  17. 25款经典老芯片,认识5款以上的工程师证明你老了!
  18. python手撕分水岭算法
  19. 新型冠状病毒的持续了解
  20. python中selenium模块驱动谷歌详解

热门文章

  1. 互联网世界无边界,想去看看未来的样子
  2. 后端验证 Facebook 登录是否有效
  3. 14- ESP8266通过mqtt服务器接收控制指令
  4. Photoshop7.0 简体中文迷你版
  5. 14场胜负彩玩法 Java版本
  6. P小于0.05的P应该是大写的P还是小写的P
  7. C#导入excel到数据库
  8. 简单的天气预报app
  9. https协议上传文件
  10. 湘潭不明原因肺炎病例样本将送WHO