SpringBoot使用Freemarker導出數據到word

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後綴,導出的文件出現異常;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章