訪問個人博客java
最近遇到項目需求須要將數據庫中的部分數據導出到 word 中,具體是在一個新聞列表中將選中的新聞導出到一個 word 中。參考了網上一些教程,實現了該功能,在此記錄下來。ajax
導出結果以下:spring
圖中爲導出的其中兩條新聞。數據庫
搜索網上導出 word 的方式有不少種,可是不少都是一筆帶過,有示例代碼的只找到了 POI 導出,和經過 FreeMarker 方式導出,可是隻是具備參考意義。本文采起使用 FreeMark 方式。apache
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.26-incubating</version> </dependency>
新建 word 替換內容爲佔位符
springboot
另存模板爲 XML 文件
多線程
使用 NotePad++ 打開 xml 文件app
選中所有內容,到這裏進行格式化工具
將原內容替換爲格式化後的內容.net
由於個人 word 的內容是一個列表,因此須要添加一個 freemarer 標籤標識
找到<w:document>
元素下面的 <w:body>
元素,添加<#list newsList news>
, 並在</w:body>
結束標籤以前閉合 </#list>
, 此處的 newsList 爲後臺讀取模板時須要須要渲染數據map集合的key, 其所對應的是一個list集合。
保存爲 FreeMarker 的模板文件,後綴爲 ftl 格式,拷貝到項目中
Map<String, Object> root = new HashMap<String, Object>(); root.put("newsList", newsList);//newsList爲新聞對象集合 String template = "/temp.ftl"; //模板文件的地址 ByteArrayOutputStream outputStream = WordUtil.process(root, template); return outputStream;
DownloadUtil.download(byteArrayOutputStream, response, returnname);注:在實現功能的時候,因爲採起的是 ajax 請求方式,致使只是將流寫入 Response 時, Response 爲 xml 格式的數據。可是想要實現的效果是彈出下載框,下載 word 文檔。最後查詢資料,修改ajax請求爲form表單提交方式(ajax form),才彈出下載框實現了功能。
//WordUtil.java import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Map; import freemarker.template.Configuration; import freemarker.template.Template; public final class WordUtil { private static Configuration configuration = null; private WordUtil() { throw new AssertionError(); } /** * 根據模板生成相應的文件 * @param root 保存數據的map * @param template 模板文件的地址 * @param path 生成的word文檔輸出地址 * @return */ public static synchronized ByteArrayOutputStream process(Map<?, ?> root, String template) { if (null == root ) { throw new RuntimeException("數據不能爲空"); } if (null == template) { throw new RuntimeException("模板文件不能爲空"); } ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); String templatePath = template.substring(0, template.lastIndexOf("/")); String templateName = template.substring(template.lastIndexOf("/") + 1, template.length()); if (null == configuration) { configuration = new Configuration(Configuration.VERSION_2_3_23); // 這裏Configurantion對象不能有兩個,不然多線程訪問會報錯 configuration.setDefaultEncoding("utf-8"); configuration.setClassicCompatible(true); } configuration.setClassForTemplateLoading(WordUtil.class, templatePath); Template t = null; try { t = configuration.getTemplate(templateName); Writer w = new BufferedWriter(new OutputStreamWriter(outputStream, "utf-8")); t.process(root, w); // 這裏w是一個輸出地址,能夠輸出到任何位置,如控制檯,網頁等 w.close(); } catch (Exception e) { throw new RuntimeException(e); } return outputStream; } }
//DownloadUtil.java import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.FileUtils; public class DownloadUtil { /** * @param byteArrayOutputStream 將文件內容寫入ByteArrayOutputStream * @param response HttpServletResponse 寫入response * @param returnName 返回的文件名 */ public static void download(ByteArrayOutputStream byteArrayOutputStream, HttpServletResponse response, String returnName) throws IOException{ response.setContentType("application/msword"); response.setHeader("Content-Disposition", "attachment; filename=" + returnName); response.setContentLength(byteArrayOutputStream.size()); OutputStream outputstream = response.getOutputStream(); //取得輸出流 byteArrayOutputStream.writeTo(outputstream); //寫到輸出流 byteArrayOutputStream.close(); //關閉 outputstream.flush(); //刷數據 } }