1.創建Freemarker模板文件
1.1 新建word文檔,輸入模板數據;
1.2 將word文檔另存爲xml文件(必須是另存爲,不是直接修改後綴名);
1.3 打開xml文件,將需要從數據庫或動態獲取的數據,使用${xx}符號替換,如:word文檔上有“姓名:張三”,具體姓名需要從數據庫動態獲取,則將“張三”替換爲“${name}”,name需要和Java代碼中Map的key值保持一致;
1.4 將xml文件的後綴名修改爲“ftl”(根據實際測試,直接使用1.3步的xml文件作爲模板文件,也可以);
2.引入jar包
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
3.工具類
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import java.io.*;
import java.util.Map;
public class WordUtil {
//配置信息
private static Configuration configuration = null;
//模板文件的位置
private static String tempPath;
public WordUtil() {
if(configuration == null){
configuration = new Configuration(Configuration.VERSION_2_3_23);
configuration.setDefaultEncoding("UTF-8");
}
if(tempPath == null ||tempPath.length()==0){
//裝載模板文件目錄
String filePath = this.getClass().getClassLoader().getResource("/").getPath();
int end = filePath.lastIndexOf("WEB-INF/");
String basePath = filePath.substring(0,end);
tempPath = basePath + "WEB-INF/page/temp/";
}
}
public byte[] getByteWord(Map dataMap, String tempName) throws IOException {
byte[] content = null;
File file = null;
InputStream in = null;
try {
//模板文件路徑
File readFile = new File(tempPath);
configuration.setDirectoryForTemplateLoading(readFile);
//加載模板文件
Template template = configuration.getTemplate(tempName);
//創建臨時文件,用於保存要導出的數據
file = new File("report.doc");
//這個地方不能使用FileWriter因爲需要指定編碼類型否則生成的Word文檔會因爲有無法識別的編碼而無法打開
Writer w = new OutputStreamWriter(new FileOutputStream(file), "utf-8");
//填充數據
template.process(dataMap, w);
//將臨時文件數據讀入文件流
in = new FileInputStream(file);
content=new byte[(int)file.length()];
in.read(content);
} catch (TemplateException e) {
e.printStackTrace();
} finally {
if(in != null) in.close();
//刪除臨時文件
if(file != null) file.delete();
}
return content;
}
public static HttpHeaders setResponseHeaderWord(String fileName){
HttpHeaders headers = new HttpHeaders();
try {
headers.add("Content-Disposition", "attachment;filename="+new String(fileName.getBytes("gbk"), "iso8859-1")+".doc");
headers.setContentType(MediaType.valueOf("application/msword"));
}catch (Exception e){
e.printStackTrace();
}
return headers;
}
}
4.接口類
@Override
public byte[] exportReportInfo(Integer id) {
byte[] bytes = null;
try {
//從數據庫獲取數據,Map中key需要和模板文件中${}中的值保持一致
Map map = this.exportMapper.selectReportExport(id);
//"<w:p></w:p>"爲word文檔支持的換行符號,將需要換行的地方進行替換
map.put("plan",map.get("plan").toString().replace("\n","<w:p></w:p>"));
//創建對象,初始化參數
WordUtil wordUtil = new WordUtil();
//獲取需要導出的字節數組
bytes = wordUtil.getByteWord(map,"report.xml");
} catch (IOException e) {
e.printStackTrace();
}
return bytes;
}
4.執行導出操作
/*導出word*/
@RequestMapping("/exportReport")
public ResponseEntity<byte[]> exportReport(Integer id){
//設置word文件名
String fileName = "員工信息";
byte[] value = null;
try {
//獲取要導出的數據
value = this.dataService.exportReportInfo(id);
}catch (Exception e){
e.printStackTrace();
}
//設置HttpHeaders,設置fileName編碼,排除導出文檔名稱亂碼問題
HttpHeaders headers = WordUtil.setResponseHeaderWord(fileName);
return new ResponseEntity(value,headers, HttpStatus.OK);
}
5.注意事項
5.1導出的word文檔名稱,需要使用.doc後綴,測試時使用.docx後綴,導出的文件出現異常;