Spring Boot 系列教程10-freemarker导出word下载
freemarker
- FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
- FreeMarker是免费的,基于Apache许可证2.0版本发布。其模板编写为FreeMarker Template Language(FTL),属于简单、专用的语言。需要准备数据在真实编程语言中来显示,比如数据库查询和业务运算, 之后模板显示已经准备好的数据。在模板中,主要用于如何展现数据, 而在模板之外注意于要展示什么数据。
最终下载效果
项目图片
操作流程
- 准备doc模版
- 另存为xml文件
- 修改名为userList.ftl后拷贝文件到src/main/resources
怎样修改userList.ftl
Eclipse下如何打开ftl文件
- 下载一个专门的ftl编辑器插件,然后在里面格式化;
- 或者设置ftl的编辑器为jsp的编辑器,用它做format,eclipse->windows->preferences
修改userList.ftl第一步
原来,注意rId4的位置
<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
Target="word/document.xml" />
现在
<#list list as user>
<Relationship Id="rId${user_index}Png"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
Target="word/document.xml" />
</#list>
修改userList.ftl第二步
原来,注意rId4的位置,image1.png
<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
Target="media/image1.png" />
现在
<#list list as user>
<Relationship Id="rId${user_index}Png"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image${user_index}.png" />
</#list>
修改userList.ftl第三步
原来
<w:tr>
<w:tblPrEx>
<w:tblBorders>
<w:top w:val="single" w:color="auto" w:sz="4" w:space="0" />
<w:left w:val="single" w:color="auto" w:sz="4" w:space="0" />
<w:bottom w:val="single" w:color="auto" w:sz="4" w:space="0" />
<w:right w:val="single" w:color="auto" w:sz="4" w:space="0" />
<w:insideH w:val="single" w:color="auto" w:sz="4" w:space="0" />
<w:insideV w:val="single" w:color="auto" w:sz="4" w:space="0" />
</w:tblBorders>
<w:tblLayout w:type="fixed" />
<w:tblCellMar>
<w:left w:w="108" w:type="dxa" />
<w:right w:w="108" w:type="dxa" />
</w:tblCellMar>
</w:tblPrEx>
<w:tc>
<w:tcPr>
<w:tcW w:w="2130" w:type="dxa" />
<w:vAlign w:val="top" />
</w:tcPr>
<w:p>
<w:pPr>
<w:pStyle w:val="4" />
<w:jc w:val="center" />
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
<w:t>111</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2130" w:type="dxa" />
<w:vAlign w:val="top" />
</w:tcPr>
<w:p>
<w:pPr>
<w:pStyle w:val="4" />
<w:jc w:val="center" />
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
<w:t>222</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2131" w:type="dxa" />
<w:vAlign w:val="top" />
</w:tcPr>
<w:p>
<w:pPr>
<w:pStyle w:val="4" />
<w:jc w:val="center" />
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
<w:t>333</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2131" w:type="dxa" />
<w:vAlign w:val="top" />
</w:tcPr>
<w:p>
<w:pPr>
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
<w:pict>
<v:shape id="_x0000_i1026" o:spt="75" alt="wx" type="#_x0000_t75" style="height:93.25pt;width:95.6pt;"
filled="f" o:preferrelative="t" stroked="f" coordsize="21600,21600">
<v:path />
<v:fill on="f" focussize="0,0" />
<v:stroke on="f" />
<v:imagedata r:id="rId4" o:title="wx" />
<o:lock v:ext="edit" aspectratio="t" />
<w10:wrap type="none" />
<w10:anchorlock />
</v:shape>
</w:pict>
</w:r>
</w:p>
</w:tc>
</w:tr>
现在
<#list list as user>
<w:tr>
<w:tblPrEx>
<w:tblBorders>
<w:top w:val="single" w:color="auto" w:sz="4" w:space="0" />
<w:left w:val="single" w:color="auto" w:sz="4" w:space="0" />
<w:bottom w:val="single" w:color="auto" w:sz="4" w:space="0" />
<w:right w:val="single" w:color="auto" w:sz="4" w:space="0" />
<w:insideH w:val="single" w:color="auto" w:sz="4" w:space="0" />
<w:insideV w:val="single" w:color="auto" w:sz="4" w:space="0" />
</w:tblBorders>
<w:tblLayout w:type="fixed" />
<w:tblCellMar>
<w:left w:w="108" w:type="dxa" />
<w:right w:w="108" w:type="dxa" />
</w:tblCellMar>
</w:tblPrEx>
<w:tc>
<w:tcPr>
<w:tcW w:w="2130" w:type="dxa" />
<w:vAlign w:val="top" />
</w:tcPr>
<w:p>
<w:pPr>
<w:pStyle w:val="4" />
<w:jc w:val="center" />
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
<w:t>${user.id}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2130" w:type="dxa" />
<w:vAlign w:val="top" />
</w:tcPr>
<w:p>
<w:pPr>
<w:pStyle w:val="4" />
<w:jc w:val="center" />
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
<w:t>${user.name}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2131" w:type="dxa" />
<w:vAlign w:val="top" />
</w:tcPr>
<w:p>
<w:pPr>
<w:pStyle w:val="4" />
<w:jc w:val="center" />
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
<w:t>${user.age}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2131" w:type="dxa" />
<w:vAlign w:val="top" />
</w:tcPr>
<w:p>
<w:pPr>
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" />
<w:lang w:val="en-US" w:eastAsia="zh-CN" />
</w:rPr>
<w:pict>
<v:shape id="_x0000_i1026" o:spt="75" alt="${user.name}" type="#_x0000_t75"
style="height:93.25pt;width:95.6pt;" filled="f" o:preferrelative="t" stroked="f"
coordsize="21600,21600">
<v:path />
<v:fill on="f" focussize="0,0" />
<v:stroke on="f" />
<v:imagedata r:id="rId${user_index}Png" o:title="${user.name}" />
<o:lock v:ext="edit" aspectratio="t" />
<w10:wrap type="none" />
<w10:anchorlock />
</v:shape>
</w:pict>
</w:r>
</w:p>
</w:tc>
</w:tr>
</#list>
修改userList.ftl第四步,关键是图片
原来
<pkg:part pkg:name="/word/media/image1.png" pkg:contentType="image/png">
<pkg:binaryData>iVBORw0KGgoAAAANSUhEUgAAAPEAAADrCAYAAAC4hnD0AAAgAElEQVR4nOx9B5wkZZn.....
gxxYtZVEXKLEIEZJxCVKDHJAxP8PvwV4N/MWQn4AAAAASUVORK5CYII=
</pkg:binaryData>
</pkg:part>
现在
<#list list as user>
<pkg:part pkg:name="/word/media/image${user_index}.png" pkg:contentType="image/png">
<pkg:binaryData>${user.headPortrait}</pkg:binaryData>
</pkg:part>
</#list>
最后祝你好运,细心,注意标签闭合,image名称对应
UserController.download方法
@Autowired
private FreeMarkerConfigurer freeMarkerConfigurer;
private Base64 b64Encoder = new Base64();
// 处理下载word文档
@RequestMapping("/download")
public void download(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 告诉浏览器用什么软件可以打开此文件
response.setHeader("content-Type", "application/msword");
// 下载文件的默认名称
response.setHeader("Content-Disposition", "attachment;filename=xx.doc");
freeMarkerConfigurer.getConfiguration().setClassForTemplateLoading(getClass(), "/");
Template template = freeMarkerConfigurer.getConfiguration().getTemplate("userList.ftl");
String webapp = request.getServletContext().getRealPath("/");
List<User> list = userRepository.findAll();
for (int i = 0; i < list.size(); i++) {
User user = list.get(i);
File file = new File(webapp, user.getHeadPortrait());
FileInputStream fis = new FileInputStream(file);
byte[] imgData = new byte[fis.available()];
fis.read(imgData);
fis.close();
String headPortrait = b64Encoder.encodeAsString(imgData);
user.setHeadPortrait(headPortrait);
}
Map<String, Object> root = new HashMap<String, Object>();
root.put("list", list);
template.process(root, new OutputStreamWriter(response.getOutputStream()));
}
user.jsp,添加的核心代码
function headPortraitFormatter(value,row,index){
if (value){
return "<img width='50' height='50' alt='je-ge' src='"+value+"'/>";
} else {
return "";
}
}
<th data-options="field:'headPortrait',width:10,formatter:headPortraitFormatter">头像</th>
<a data-url="downloadUser" href="javascript:void(0)" class="easyui-linkbutton c5" iconCls="icon-reload">word下载</a>
其他关联代码
- Spring Boot 系列教程7-EasyUI-datagrid
http://blog.csdn.net/je_ge/article/details/53365189 - Spring Boot 系列教程5-热部署-devtools模块
http://blog.csdn.net/je_ge/article/details/53326525 - Spring Boot 系列教程2-Data JPA
http://blog.csdn.net/je_ge/article/details/53294949
注意事项
- 最后还是要祝你好运,还是细心,注意标签闭合,image名称对应
源码地址
https://github.com/je-ge/spring-boot
如果觉得我的文章对您有帮助,请予以打赏。您的支持将鼓励我继续创作!谢谢!
Spring Boot 系列教程10-freemarker导出word下载的更多相关文章
- Spring Boot 系列教程18-itext导出pdf下载
Java操作pdf框架 iText是一个能够快速产生PDF文件的java类库.iText的java类对于那些要产生包含文本,表格,图形的只读文档是很有用的.它的类库尤其与java Servlet有很好 ...
- Spring Boot 系列教程12-EasyPoi导出Excel下载
Java操作excel框架 Java Excel俗称jxl,可以读取Excel文件的内容.创建新的Excel文件.更新已经存在的Excel文件,现在基本没有更新了 http://jxl.sourcef ...
- Spring Boot 系列教程11-html页面解析-jsoup
需求 需要对一个页面进行数据抓取,并导出doc文档 html解析器 jsoup 可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS以及类似于JQuery的操 ...
- Spring Boot 系列教程16-数据国际化
internationalization(i18n) 国际化(internationalization)是设计和制造容易适应不同区域要求的产品的一种方式. 它要求从产品中抽离所有地域语言,国家/地区和 ...
- Spring Boot 系列教程15-页面国际化
internationalization(i18n) 国际化(internationalization)是设计和制造容易适应不同区域要求的产品的一种方式. 它要求从产品中抽离所有地域语言,国家/地区和 ...
- Spring Boot 系列教程14-动态修改定时任务cron参数
动态修改定时任务cron参数 不需要重启应用就可以动态的改变Cron表达式的值 不能使用@Scheduled(cron = "${jobs.cron}")实现 DynamicSch ...
- Spring Boot 系列教程9-swagger-前后端分离后的标准
前后端分离的必要 现在的趋势发展,需要把前后端开发和部署做到真正的分离 做前端的谁也不想用Maven或者Gradle作为构建工具 做后端的谁也不想要用Grunt或者Gulp作为构建工具 前后端需要通过 ...
- Spring Boot 系列教程8-EasyUI-edatagrid扩展
edatagrid扩展组件 edatagrid组件是datagrid的扩展组件,增加了统一处理CRUD的功能,可以用在数据比较简单的页面. 使用的时候需要额外引入jquery.edatagrid.js ...
- Spring Boot 系列教程7-EasyUI-datagrid
jQueryEasyUI jQuery EasyUI是一组基于jQuery的UI插件集合体,而jQuery EasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面.开发者不需要 ...
随机推荐
- spoj1811:Longest Common Substrin
题目链接:http://begin.lydsy.com/JudgeOnline/problem.php?id=2796 把一个字符串做出后缀自动机,另一个字符串与之匹配. #include<cs ...
- Java 反射 Class对象
Java 反射 Class对象 @author ixenos 关键字:RTTI.动态绑定.动态加载.获得Class引用.泛型Class引用.newInstance的坑.JVM中的泛型类型信息 RTTI ...
- 2、Spring的 IoC详解(第一个Spring程序)
Spring是为了解决企业应用开发的复杂性而创建的一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架.在这句话中重点有两个,一个是IoC,另一个是AOP.今天我们讲第一个IoC. IoC概念 ...
- Linux Root密码忘记怎么办?用Vultr vps教程演示重置root密码
使用vultr免费提供的snapshots功能,可以轻松备份vps镜像,通常会碰到一个问题:恢复镜像后,vps的root密码失效了.正常情况下,root密码是镜像文件里的root密码,在某些情况下,由 ...
- wuzhi 五指 数据库仿 thinkphp
在/coreframe/app/模块/libs/class/mydb.class.php 中编辑 调用 : $mydb = load_class("mydb","模块&q ...
- id和instancetype的异同
相同点: 都可以作为方法返回值类型 在initWithName:方法中是一样的,例如: - (id)initWithName:(NSString *)name; - (instancetype)ini ...
- mnesia
1.模式创建 mnesia:create_schema([node()|nodes()]).集群的节点之间创建模式 2.启动和停止 application:start(mnesia). applica ...
- 第2章 熟悉Eclipse开发工具----加减乘除,和差积商的英文写法
加减乘除表示运算:plus minus multiply divide和差积商表示运算结果:sum difference product quotient
- POJ 2488 A Knight's Journey(深搜+回溯)
A Knight's Journey Time Limit : 2000/1000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other) ...
- 配置mac自带的Apache服务器
第一步: 484 cd /etc/apache2 备份httpd.conf文件,以防万一 486 sudo cp httpd.conf httpd.conf.bak 如果操作错误,可以通过 491 ...