Java之word導出下載


訪問我的博客

前言

最近遇到項目需求需要將數據庫中的部分數據導出到 word 中,具體是在一個新聞列表中將選中的新聞導出到一個 word 中。參考了網上一些教程,實現了該功能,在此記錄下來。

導出結果如下:

mark

圖中為導出的其中兩條新聞。

搜索網上導出 word 的方式有很多種,但是很多都是一筆帶過,有示例代碼的只找到了 POI 導出,和通過 FreeMarker 方式導出,但是只是具有參考意義。本文采取使用 FreeMark 方式。

實現步驟

  1. Maven 工程引入FreeMarker 的依賴,非 Maven 工程添加 jar 包
<dependency>
  <groupId>org.freemarker</groupId>
  <artifactId>freemarker</artifactId>
  <version>2.3.26-incubating</version>
</dependency>
  1. 創建 word 模板

    1. 新建 word 替換內容為占位符
      mark

    2. 另存模板為 XML 文件
      mark

    3. 使用 NotePad++ 打開 xml 文件

    4. 選中全部內容,到這里進行格式化

    5. 將原內容替換為格式化后的內容

    6. 因為我的 word 的內容是一個列表,所以需要添加一個 freemarer 標簽標識

    7. 找到 <w:document> 元素下面的 <w:body> 元素,添加 <#list newsList news> , 並在</w:body>結束標簽之前閉合 </#list>, 此處的 newsList 為后台讀取模板時需要需要渲染數據map集合的key, 其所對應的是一個list集合。
      mark

    8. 保存為 FreeMarker 的模板文件,后綴為 ftl 格式,拷貝到項目中
      mark

  2. 編寫代碼

    1. 從數據中查詢數據集合放入Map中, 調用工具方法,返回流
    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;
    
    1. 調用下載工具類進行下載即可。
    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();											//刷數據
	}
}

源碼下載

點我下載

參考鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM