java后台利用模板生成Word文档提供前台下载

原文地址:https://blog.csdn.net/u010251278/article/details/52398578

2016.12.06更新,java后台利用Apache poi生成Excel文档提供前台下载,博客链接http://blog.csdn.net/u010251278/article/details/53491258

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

在博主完成尚未完成的web项目的过程中,又遇到了这样一个需求,当用户点击相关按钮时,系统依据模板生成一份Word文档并提供下载。

实现的依据参考了这篇博客,现在将我的实现过程记录下来,为后人行个方便也为自己留个记录。

首先要指出的是,实现的思路和freeMarker差不离,将.doc的文档做相应的转换后转为.ftl文档,其中的变量会以${xxx}来代替,这样就可以

使用freeMarker模板引擎来替换变量啦为例,动态生成文件后发送到浏览器端提供用户下载。所以,实现该功能分为以下几个步骤,以我的

项目为例,一些敏感的信息可能不予展示,但不影响该功能的学习。

1.为你的项目导入freeMarker包

我的项目是依靠maven来维护依赖的,所以引入很方便,只需要在pom文件中加入下面这个依赖就好

[html]  view plain  copy
  1. <dependency>  
  2.     <groupId>org.freemarker</groupId>  
  3.     <artifactId>freemarker</artifactId>  
  4.     <version>2.3.23</version>  
  5. </dependency>  

如果还是比较传统的话,就像那个链接里的项目一样,把jar包导入项目吧

2.依据模板动态生成word文档,首先你得有个模板

模板是doc类型就好,注意不是docx,docx没有尝试,doc类型已经满足了我的需求,朋友们如果尝试成功了可以告诉我一下

test.doc,注意“产品品质证明书”是一张图片哦,图片会漂亮的留在生成的新文档中。将变量替换成${xxx}即可,这里只选了两

个变量


3.点击 文件->另存为 将test.doc保存为xml类型,即 Word XML文档 .xml类型 ,得到test.xml

4.用notepad或者sublime打开test.xml,你会发现${xxx}会被分割成${*********xxx********)的样子,将*******删除,保证它又成了完整的变量

标签,像这样


5.将文件已utf-8编码保存,另存为为.ftl,找不到该格式直接改文件后缀名就行,这样得到test.ftl

6.前台触发事件

我的项目是基于SpringMVC的,所以前台触发只需要在view层的文件里加个按钮事件即可,直接上代码

[javascript]  view plain  copy
  1. function generateMillCertificate(id) {//点击下载按钮触发的事件  
  2.         window.location.href = '../deliveryOrder/exportMillCertificate?id=' + id;  
  3.     }  
7.后台生成文件,并返回给客户的浏览器

这里又分为两步

a.controller层接收请求,根据参数拼凑数据,放在map中

[java]  view plain  copy
  1. /*** 
  2.      * 导出Word材质单 
  3.      * 
  4.      * @return 
  5.      * @throws Exception 
  6.      */  
  7.     @RequestMapping(value = "exportMillCertificate", method = RequestMethod.GET)  
  8.     @ResponseBody  
  9.     public void exportMillCertificate(HttpServletRequest request,  
  10.                       HttpServletResponse response) throws Exception {  
  11.         //获得数据,系统相关,就不展示了  
  12.         Map<String, Object> map = new HashMap<String, Object>();  
  13.         map.put("customerShortName",deliveryOrder.getRepositoryName());  
  14.         map.put("productName",deliveryOrderDetail.getProductName());  
  15.         WordUtils.exportMillCertificateWord(request,response,map);  
  16.     }  
b.工具类WordUtils利用传来的map和将要返回给用户的HTTPServletReponse,将map里的数据和模板中${xxx}标签对应的变量值填入,

生成新的文档,通过response返回给浏览器并提供用户下载

[java]  view plain  copy
  1. public class WordUtils {  
  2.     //配置信息,代码本身写的还是很可读的,就不过多注解了  
  3.     private static Configuration configuration = null;  
  4.     //这里注意的是利用WordUtils的类加载器动态获得模板文件的位置  
  5.     private static final String templateFolder = WordUtils.class.getClassLoader().getResource("../../").getPath() + "asserts/templete/";  
  6.     static {  
  7.         configuration = new Configuration();  
  8.         configuration.setDefaultEncoding("utf-8");  
  9.         try {  
  10.             configuration.setDirectoryForTemplateLoading(new File(templateFolder));  
  11.         } catch (IOException e) {  
  12.             e.printStackTrace();  
  13.         }  
  14.    }  
  15.   
  16.     private WordUtils() {  
  17.         throw new AssertionError();  
  18.     }  
  19.   
  20.     public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map) throws IOException {  
  21.         Template freemarkerTemplate = configuration.getTemplate("test.ftl");  
  22.         File file = null;  
  23.         InputStream fin = null;  
  24.         ServletOutputStream out = null;  
  25.         try {  
  26.             // 调用工具类的createDoc方法生成Word文档  
  27.             file = createDoc(map,freemarkerTemplate);  
  28.             fin = new FileInputStream(file);  
  29.   
  30.             response.setCharacterEncoding("utf-8");  
  31.             response.setContentType("application/msword");  
  32.             // 设置浏览器以下载的方式处理该文件名  
  33.             String fileName = "材质单"+DateUtils.curDateTimeStr14() + ".doc";  
  34.             response.setHeader("Content-Disposition""attachment;filename="  
  35.                     .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));  
  36.   
  37.             out = response.getOutputStream();  
  38.             byte[] buffer = new byte[512];  // 缓冲区  
  39.             int bytesToRead = -1;  
  40.             // 通过循环将读入的Word文件的内容输出到浏览器中  
  41.             while((bytesToRead = fin.read(buffer)) != -1) {  
  42.                 out.write(buffer, 0, bytesToRead);  
  43.             }  
  44.         } finally {  
  45.             if(fin != null) fin.close();  
  46.             if(out != null) out.close();  
  47.             if(file != null) file.delete(); // 删除临时文件  
  48.         }  
  49.     }  
  50.   
  51.     private static File createDoc(Map<?, ?> dataMap, Template template) {  
  52.         String name =  "test.doc";  
  53.         File f = new File(name);  
  54.         Template t = template;  
  55.         try {  
  56.             // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开  
  57.             Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");  
  58.             t.process(dataMap, w);  
  59.             w.close();  
  60.         } catch (Exception ex) {  
  61.             ex.printStackTrace();  
  62.             throw new RuntimeException(ex);  
  63.         }  
  64.         return f;  
  65.     }  
  66. }  
8.可以运行试试看啦,给你看我生成的新文档



是不是完美的一腿。写到这里就结束啦。


猜你喜欢

转载自blog.csdn.net/younger_z/article/details/80256085