通过freemarker生成一个word,解决生成的word用wps打开有问题的问题,解决出word时中文文件名乱码问题,解决打开出word时打开的word出现问题的问题,出图片,解决动态列表
通过freemarker制作word比较简单
步骤:制作word模板。制作方式是:将模板word保存成为xml----在xml的word模板中添加相应的标记----将xml的word文件的后缀名改成ftl文件(要注意的是生成xml格式要是2003格式的xml,也就是说拿到的word模板得是2003格式的,否则用wps打开word将会出现问题)
详细步骤如下:
模板制作(将要动态显示的数据打上标记,这个标记是freemarker中的EL标记,要注意的是,要控制值为空的情况,下面${(site.wzmc)?default(“”)}标识当网站名称为空的时候显示空值,如果这里如果不做控制,在实际项目中会显示错误!)
另外要注意的是:
一、不要直接在word中替换掉文字的方式添加标记,这种会有问题。
二、不要使用Eclipse对xml文件进行格式化,这种生成word的时候会提示文档有问题。解决这个的问题是通过firstobject对word的xml进行格式化,对xml进行编辑。(使用firstobject打开带有中文文件名的xml文件的时候,会出现问题,建议使用英文word文档名称)
三、firstobject下载地址:http://www.firstobject.com/dn_editor.htm
其中,要想软件能够格式化xml代码,需要进行设置,设置方式是:打开firstobject----Tools-----Preferences------Format-----Tabs
点击Indent,结果xml变成了有格式化的,效果图如下:
常见标签:
行标记:
<w:p w:rsidR="00790C22"w:rsidRPr="00C07F75" w:rsidRDefault="00790C22"w:rsidP="004018B7">
标识是一个表格的标签
<w:tbl></w:tb1>
表格行:
<w:trw:rsidR="00790C22" w:rsidRPr="00C07F75"w:rsidTr="004018B7"></w:tr>
表格中的单元格:
<w:tc></w:tc>
循环输出数据的方式
|
<#list problemInfoInterview as problemInfo> <w:tbl> <w:tblPr> <w:tblW w:w="0" w:type="auto"/> <w:tblBorders> <w:top w:val="single" w:sz="4" w:space="0" w:color="auto"/> <w:left w:val="single" w:sz="4" w:space="0" w:color="auto"/> <w:bottom w:val="single" w:sz="4" w:space="0" w:color="auto"/> <w:right w:val="single" w:sz="4" w:space="0" w:color="auto"/> <w:insideH w:val="single" w:sz="4" w:space="0" w:color="auto"/> <w:insideV w:val="single" w:sz="4" w:space="0" w:color="auto"/> </w:tblBorders> <w:tblLook w:val="04A0" w:firstRow="1" w:lastRow="0" w:firstColumn="1" w:lastColumn="0" w:noHBand="0" w:noVBand="1"/> </w:tblPr> <w:tblGrid> <w:gridCol w:w="2235"/> <w:gridCol w:w="6287"/> </w:tblGrid> <w:tr w:rsidR="00790C22" w:rsidRPr="00C07F75" w:rsidTr="004018B7"> <w:tc> <w:tcPr> <w:tcW w:w="2235" w:type="dxa"/> <w:shd w:val="clear" w:color="auto" w:fill="auto"/> <w:vAlign w:val="center"/> </w:tcPr> <w:p w:rsidR="00790C22" w:rsidRPr="00C07F75" w:rsidRDefault="00790C22" w:rsidP="004018B7"> <w:pPr> <w:jc w:val="center"/> <w:rPr> <w:rFonts w:ascii="Times New Roman" w:eastAsia="黑体" w:hAnsi="Times New Roman"/> <w:sz w:val="24"/> <w:szCs w:val="24"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:ascii="Times New Roman" w:eastAsia="黑体" w:hAnsi="Times New Roman" w:hint="eastAsia"/> <w:sz w:val="24"/> <w:szCs w:val="24"/> </w:rPr> <w:t>问题名称</w:t> </w:r> </w:p> </w:tc> <w:tc> <w:tcPr> <w:tcW w:w="6287" w:type="dxa"/> <w:shd w:val="clear" w:color="auto" w:fill="auto"/> <w:vAlign w:val="center"/> </w:tcPr> <w:p w:rsidR="00790C22" w:rsidRPr="00C07F75" w:rsidRDefault="00790C22" w:rsidP="004018B7"> <w:pPr> <w:jc w:val="left"/> <w:rPr> <w:rFonts w:ascii="Times New Roman" w:eastAsia="宋体" w:hAnsi="Times New Roman"/> <w:sz w:val="24"/> <w:szCs w:val="24"/> </w:rPr> </w:pPr> <w:r> <w:rPr> <w:rFonts w:ascii="Times New Roman" w:eastAsia="宋体" w:hAnsi="Times New Roman" w:hint="eastAsia" /> <w:sz w:val="24" /> <w:szCs w:val="24" /> </w:rPr> <w:t>${(problemInfo.problemName)?default("")}</w:t> </w:r> </w:p> </w:tc> </w:tr> 这里面的行删除 </w:tbl> <w:p w:rsidR="007F35A8" w:rsidRPr="007F35A8" w:rsidRDefault="007F35A8" w:rsidP="007F35A8" /> -4-5下午6:02:11 *@version V1.0 */ publicclass FreeMarkerUtil { privatestatic Configurationconfiguration =null; privatestatic Map<String, Template>allTemplates =null; static { configuration =new Configuration(); configuration.setDefaultEncoding("utf-8"); //configuration.setClassForTemplateLoading(FreeMarkerUtil.class, // "../template"); try { configuration.setDirectoryForTemplateLoading( new File(TemplateUtil.reportTemplatePath)); }catch (IOException e1) { e1.printStackTrace(); } allTemplates =new HashMap<String, Template>(); try { allTemplates.put("word",configuration.getTemplate(TemplateUtil.templateFileName)); }catch (Exception e) { e.printStackTrace(); thrownew RuntimeException(e); } } public FreeMarkerUtil() { } publicstatic File createDoc(Map<?, ?> dataMap,String type){ String name ="temp" + (int) (Math.random() * 100000) +".doc"; File f =new File(name); Template t =allTemplates.get(type); try { //这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word //文档会因为有无法识别的编码而无法打开 Writer w =new OutputStreamWriter(new FileOutputStream(f),"utf-8"); t.process(dataMap, w); w.close(); }catch (Exception ex) { ex.printStackTrace(); thrownew RuntimeException(); } return f; } publicstatic String getImageString(String fileName)throws IOException { InputStream in =null; byte[] data =null; try { in =new FileInputStream(fileName); data =newbyte[in.available()]; in.read(data); in.close(); }catch (Exception e) { e.printStackTrace(); }finally { if (in !=null){ in.close(); } } Base64Encoder encoder =new Base64Encoder(); return data !=null ? encoder.encode(data) :""; } } |
出Word的Controller层的代码,并解决出word时中文文件名乱码的问题
|
package com.ucap.netcheck.controller; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import java.util.Map; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.ucap.netcheck.entity.Site; import com.ucap.netcheck.entity.User; import com.ucap.netcheck.service.IReport2WordService; import com.ucap.netcheck.service.ISiteService; import com.ucap.netcheck.utils.DateUtil; import com.ucap.netcheck.utils.FreeMarkerUtil; /** * @Title: Report2WordController.java * @Package com.ucap.netcheck.controller * @Description:生成word部分的Controller * @author Zuoquan Tu * @date 2015-4-12上午9:36:43 * @version V1.0 */ @Controller @RequestMapping(value = "/reportToWord", method = { RequestMethod.GET, RequestMethod.POST }) public class Report2WordController { @Autowired private IReport2WordService report2WordService; @Autowired private ISiteService siteService; @RequestMapping(value = "/word") public String outWord(Model model, HttpServletRequest request, HttpServletResponse response) throws Exception { request.setCharacterEncoding("utf-8"); //获取innerUUID,taskId String siteCode = request.getParameter("innerUUID"); //获取taskId Integer taskId = Integer.parseInt(request.getParameter("taskId")); //获取用户的userId User user = (User) request.getSession().getAttribute("user"); //通过下面的方式获得模板的参数 Site site = siteService.findSite(siteCode); String webSiteName = site.getWzmc(); Map<String, Object> map = report2WordService.generateWordData(siteCode, taskId, user.getId()); //获取innerUUID,taskId // Map<String, Object> map = new HashMap<String, Object>(); //获取innerUUID,taskId // Map<String, Object> map = new HashMap<String, Object>(); // map.put("taskNum", "测试"); // map.put("tackRunNum", "测试2……rqwrqw"); // String imageStr = new FreeMarkerUtil().getImageString("D:/1.png"); // map.put("imgStr", imageStr); // // List<CheckService> newsList = new ArrayList<CheckService>(); // for (int i = 0; i < 10; i++) { // CheckService checkService = new CheckService(); // checkService.setTaskRunNum(10); // checkService.setTaskNum(1000); // newsList.add(checkService); // } // map.put("newList", newsList); this.generateWord(request,response, map, webSiteName); return null; } @SuppressWarnings("static-access") private void generateWord(HttpServletRequest request,HttpServletResponse response, Map<String, Object> map, String webSiteName) throws FileNotFoundException, IOException { File file = null; InputStream fin = null; ServletOutputStream out = null; try { //调用工具类WordGenerator的createDoc方法生成Word文档 file = new FreeMarkerUtil().createDoc(map, "word"); fin = new FileInputStream(file); response.setCharacterEncoding("utf-8"); response.setContentType("application/msword"); //设置浏览器以下载的方式处理该文件默认名为下面的文件,按照时间来生成的一个文件名称 String longMsDateStr = DateUtil.getStringLongMsDate(); String fileName = webSiteName + "_" + longMsDateStr + ".doc"; //设置下载用的文件名 setFileDownloadHeader(request, response, fileName); //response.addHeader("Content-Disposition", "attachment;filename=" + fileName); out = response.getOutputStream(); byte[] buffer = new byte[512]; int bytesToRead = -1; //通过循环将读入的Word文件的内容输出到浏览器中 while ((bytesToRead = fin.read(buffer)) != -1) { out.write(buffer, 0, bytesToRead); } } finally { if (fin != null) fin.close(); if (out != null) out.close(); if (file != null) file.delete(); //删除临时文件 } } /** *根据当前用户的浏览器不同,对文件的名字进行不同的编码设置,从而解决不同浏览器下文件名中文乱码问题 */ public static void setFileDownloadHeader(HttpServletRequest request, HttpServletResponse response, String fileName) { final String userAgent = request.getHeader("USER-AGENT"); try { String finalFileName = null; if (StringUtils.contains(userAgent, "MSIE")) { // IE浏览器 finalFileName = URLEncoder.encode(fileName, "UTF8"); } else if (StringUtils.contains(userAgent, "Mozilla")) { // google,火狐浏览器 finalFileName = new String(fileName.getBytes(), "ISO8859-1"); } else { //其他浏览器 finalFileName = URLEncoder.encode(fileName, "UTF8"); } //这里设置一下让浏览器弹出下载提示框,而不是直接在浏览器中打开 response.setHeader("Content-Disposition", "attachment; filename=\"" + finalFileName + "\""); } catch (Exception e) { e.printStackTrace(); } } } |
ServiceImpl层的实现类
|
package com.ucap.netcheck.service.impl; import java.text.NumberFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ucap.netcheck.combination.beans.TargetTypeParentToChildBean; import com.ucap.netcheck.dao.IReport2WordDao; import com.ucap.netcheck.entity.CheckService; import com.ucap.netcheck.entity.MainPageScanFail; import com.ucap.netcheck.entity.MainPageScanResult; import com.ucap.netcheck.entity.ProblemInfo; import com.ucap.netcheck.entity.Site; import com.ucap.netcheck.entity.SiteService; import com.ucap.netcheck.service.CheckServiceService; import com.ucap.netcheck.service.IReport2WordService; import com.ucap.netcheck.service.ISingleRejectResultService; import com.ucap.netcheck.service.ISiteService; import com.ucap.netcheck.service.SiteServService; import com.ucap.netcheck.service.TargetTypeService; import com.ucap.netcheck.utils.DateUtil; /** * @Title: Report2WordServiceImpl.java * @Package com.ucap.netcheck.service.impl * @Description: * @author * @date 2015-4-12上午11:58:09 * @version V1.0 */ @Service public class Report2WordServiceImpl implements IReport2WordService { @Autowired private ISiteService siteService; @Autowired private CheckServiceService checkServiceService; @Autowired private IReport2WordDao report2WordDao; @Autowired private TargetTypeService targetTypeService; @Autowired private ISingleRejectResultService singleRejectResultService; @Autowired private SiteServService siteServService; /** * generateWordData(通过这个方法获得生成报告所需的数据) * * @Title: generateWordData * @Description:通过这个方法获得生成报告所需的数据 * @param @return 返回所需的数据 * @return Map<String,Object> 返回的数据 * @throws */ @Override public Map<String, Object> generateWordData( String siteCode,Integer taskId,String userId) { Map<String, Object> map = new HashMap<String, Object>(); //网站名称,首页网址,报告编号,报告日期 Site site = siteService.findSite(siteCode); map.put("site", site); //生成报告编号和报告日期 map.put("reportCode", DateUtil.getNowDateStr() + "_" + taskId); map.put("reportDate", DateUtil.getYearMonthAndDay()); //检查方法的数据,获得CheckService的值 //通过siteCode查找site_service SiteService siteService = siteServService.findSiteService(siteCode); CheckService checkService = report2WordDao.findCheckService(siteService.getServId()); map.put("checkService", checkService); //设置开通时间的日期 map.put("checkServiceOpenTime", DateUtil.dateToStr(checkService.getOpenTime())); //设置结束时间的日期 map.put("checkServiceCloseTime", DateUtil.dateToStr(checkService.getCloseTime())); return map; } } |
Ftl语法:
|
一、判断list的channelUpdateResults是否为空,判断list的大小是否大于某个值,注意加括号 |
|
<#if channelUpdateResults??> <#if (channelUpdateResults?size>=10) > 未更新数量为“单项否决”。 </#if> </#if> |
|
二、list迭代 |
|
<#list queryMainPageScanFailList as mainPageScanFail> </#list> |
|
四、迭代的时候输出序号 |
|
${( mainPageScanFail _index+1)?default("")} 其中 |
|
五、if语句中取数组的值 |
|
<#if deadUrl[0] == 1> 是 <#else> 否 </#if> |
|
六、<#assign>赋值,并且通过x_has_next来辨别当前项是否是序列的最后一项的布尔值。 |
|
<#assign seq = ["winter", "spring", "summer", "autumn"]> <#list seq as x> ${x_index+ 1}. ${x}<#ifx_has_next>,</#if> </#list> |
七、解决出word中因为特殊字符“&”出现的问题,同时判断字符串为NULL和“”空字符串。如果在链接地址中出现了&字符,在生成的word会报错,解决办法是将这个特殊字符用“&”替换掉,示例加链接的代码如下:
| <#if (channelUpdate.url)??> <w:hlink w:dest="${(channelUpdate.url)?replace('&','&')}"> <w:r wsp:rsidR="002F59FF" wsp:rsidRPr="002F59FF"> <w:rPr> <w:rStyle w:val="ab"/> <w:rFonts w:ascii="仿宋" w:fareast="仿宋" w:h-ansi="仿宋"/> <wx:font wx:val="仿宋"/> <w:sz w:val="24"/> <w:sz-cs w:val="30"/> </w:rPr> <w:t>${(channelUpdate.url)?replace('&','&')}</w:t> </w:r> </w:hlink> </#if> |
八、多次替换以及replace多次:
${(problemInfo.problemUrl)?replace("&","&")?replace("<","<")?replace(">",">")}
通过freemarker生成一个word,解决生成的word用wps打开有问题的问题,解决出word时中文文件名乱码问题,解决打开出word时打开的word出现问题的问题,出图片,解决动态列表的更多相关文章
- 解决COS、FileUpload上传文件时中文文件名乱码问题
方法: MultipartParser mp = new MultipartParser(request, 10*1024*1024); mp.setEncoding("GBK") ...
- Ubuntu下解决解压zip文件中文文件名乱码问题
在Ubuntu下解压Windows下压缩的zip文件时,会出现解压出的带中文文件名的文件名乱码,这是因为Ubuntu和Windows默认的编码不同,Ubuntu下默认的编码是UTF-8,而Window ...
- 完美解决ExtJs6上传中文文件名乱码,后端SpringMVC
ExtJs上传中文文件名乱码,观察请求. ExtJs6上传乱码从后台无法解决,因为文件名请求里面就已经乱码了,后台无法解码. 除非请求参数正确没有乱码,后台因为编码设置不一样,可以通过后台处理乱码 这 ...
- linux 学习解决归档管理器打开rar和zip中文文件名乱码问题
在ubunut下打开windows下压缩的rar文件和zip压缩文件出现中文文件名乱码的问题真的很头疼.文件名乱码其实也没有什么关系是不?至少重命名再改回来或者是使用英文命名都可以克服.不巧的是,如此 ...
- 如何解决 Matlab 画图时中文显示乱码的问题?
使用的是win10系统,从前几个月某一天,我的matlab的figure里的中文都变成了口口.很是郁闷,还以为是动到了什么配置引起的. 前几天更新了matlab 2018b,发现还有这个问题.就觉得不 ...
- Java ZIP压缩和解压缩文件(解决中文文件名乱码问题)
Java ZIP压缩和解压缩文件(解决中文文件名乱码问题) 学习了:http://www.tuicool.com/articles/V7BBvy 引用原文: JDK中自带的ZipOutputStrea ...
- dotnetcore下解压zip文件,解决中文文件名乱码问题
(迄今为止网上那些说的用Encoding.Default解决中文文件名乱码的都不能真正解决问题!) 1.在程序开始处 Encoding.RegisterProvider(CodePagesEncodi ...
- 解决Linux与Windows压缩解压中文文件名乱码(转载)
转自:http://crazyfeng.com/linux-windows-compress-chinese-filename.html 由于Linux与Windows编码问题,使用Zip Tar 压 ...
- 上传文件,经过Zuul,中文文件名乱码解决办法
转载请标明出处: http://blog.csdn.net/forezp/article/details/77170470 本文出自方志朋的博客 问题描述 在项目中又一个上传文件的oss服务,直接调用 ...
随机推荐
- 读书笔记-《Maven实战》-2018/4/16
第一章:Maven简介 1:Maven:Maven原本的单词意思为"知识的积累",谷歌翻译为"行家",而作为Apache的开源项目,Maven是一个主要服务于基 ...
- Java阻塞队列的实现
阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞.试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列 ...
- 打造适合你的ABP(1)---- 完善日志系统
最近使用Abp开发了一个项目,对abp有一个大概的了解,第一个小项目接近尾声,新的项目马上开始,针对开发第一个项目中发现的问题及不方便的地方,本人做一些修改,特此记录,请大家多多指正! 本人的开发环境 ...
- c++指针函数的使用——回调函数
/* 函数指针 函数也是有地址的 所谓函数指针,就是指向函数的指针,函数指针也是一个变量,可以指向不同的函数.同时通过函数指针可以调用其指向函数,从而使函数的调用更加灵活. 函数指针的用途 */ #i ...
- js简单备忘录
<section class="myMemory"> <h3 class="f-tit">记事本</h3> <div ...
- map函数、filer函数、reduce函数的用法和区别
Map函数 map函数的用法如下: def add_one(x): return x+1 #使用普通函数 v1 = map(add_one,[1,2,3]) v1 = list(v1) print(v ...
- C# 定积分求周长&面积原理 代码实现
前言: 前些日子,因为工作原因,接触到了求解曲线周长,真的是搞了很久,学生时代真的很简单,但是如今的我来说,忘记了....很多人跟我应该一样. 所以来巩固加强一下记忆.一开始的时候,求周长嘛,找公式呗 ...
- cassandra 3.x官方文档(5)---探测器
写在前面 cassandra3.x官方文档的非官方翻译.翻译内容水平全依赖本人英文水平和对cassandra的理解.所以强烈建议阅读英文版cassandra 3.x 官方文档.此文档一半是翻译,一半是 ...
- User-Agent-Switcher和fiddler
浏览器模拟器(可以模拟各种浏览器效果,浏览器中看手机显示的效果) http://chromecj.com/web-development/2014-09/70.html User-Agent-Swit ...
- MacOS和iOS开发中异步调用与多线程的区别
很多童鞋可能对Apple开发中的异步调用和多线程的区别不是太清楚,这里本猫将用一些简单的示例来展示一下它们到底直观上有神马不同. 首先异步调用可以在同一个线程中,也可以在多个不同的线程中.每个线程都有 ...