通過maven引入需要的依賴
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
創建導出模版
1、首先創建一個word模版文檔,模版如下圖
word模版地址:https://github.com/hack-feng/Java-Notes/blob/master/src/note/images/exportword/test.doc
注意word中的佔位符的格式,就是freemaker的格式
詳細解釋如下:
- 文字處理:
直接用${} 中間爲替換的字段名。
如果直接在word裏面定義${title},在轉換成xml的時候有可能會被一些編碼隔開,這個時候只需要用word打開xml,將這些內容重新輸入一遍。
可以用瀏覽器打開xml,檢出自己定義的${}的內容是否都在一起,是否有被編碼隔開的情況。
- 圖片處理:
需要在word文檔模版中插入圖片
將word轉換成xml後,打開xml,會將我們的圖片轉換成長長的一段base64。
我們把base64換成我們的${pic}就可以了,pic爲字段名,可任意替換
- 列表處理:
需要在word文檔模版中插入表格
找到第二個<w:tr>
,在其前面添加 <#list peopleList as list> 其中 peopleList是傳入list的集合名稱 list 是別名。
參數取值爲:${list.name}這樣。
在與<w:tr>
配對的</w:tr>後面添加</#list>。 語法同freemaker的for循環語法
創建ftl模板
將上述word文檔另存爲test.xml格式,另存完之後可以用瀏覽器打開test.xml文件,查看我們的佔位符是否標準
注意:佔位符有時候會發生被隔開的情況,如下圖:
圖片的替換同上面的說明,圖片爲一串長長的base64,如下圖所示:
然後將文件放置resources/template/voice目錄下,並將後綴名改爲ftl。
放置在resource目錄下即可,剩下的目錄根據自己需求定製。注意要與WordUtil.java中的目錄對應。
編寫程序
通用的導出工具類
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.*;
import java.util.Map;
public class WordUtil {
private final Configuration configuration;
public WordUtil(){
configuration = new Configuration();
configuration.setDefaultEncoding("UTF-8");
}
public void createWord(Map<String,Object> dataMap, String templateName, String fileName){
//模板文件所在路徑
configuration.setClassForTemplateLoading(this.getClass(), "/template/voice");
Template t;
try {
//獲取模板文件
t = configuration.getTemplate(templateName);
} catch (IOException e) {
e.printStackTrace();
}
//導出文件
File outFile = new File(fileName);
try {
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
if (t != null) {
//將填充數據填入模板文件並輸出到目標文件
t.process(dataMap, out);
}
out.close();
} catch (IOException | TemplateException e1) {
e1.printStackTrace();
}
}
}
瀏覽器請求接口詳情
@RestController
@RequestMapping
public class VoiceInfoController{
/**
* 文字處理:
* 直接用${} 中間爲替換的字段名。
* 如果直接在word裏面定義${title},在轉換成xml的時候有可能會被一些編碼隔開,這個時候只需要用word打開xml,將這些內容重新輸入一遍。
* 可以用瀏覽器打開xml,檢出自己定義的${}的內容是否都在一起,是否有被編碼隔開的情況。
* 圖片處理:
* 需要在word文檔模版中插入圖片
* 將word轉換成xml後,打開xml,會將我們的圖片轉換成長長的一段base64。
* 我們把base64換成我們的${pic}就可以了,pic爲字段名,可任意替換
* 列表處理:
* 需要在word文檔模版中插入表格
* 找到第二個<w:tr>,在其前面添加 <#list peopleList as list> 其中 peopleList是傳入list的集合名稱 list 是別名。
* 參數取值爲:${list.name}這樣。
* 在與<w:tr>配對的</w:tr>後面添加</#list>。 語法同freemaker的for循環語法
*/
@GetMapping("/exportWord")
public Result exportWord(HttpServletRequest request, HttpServletResponse response) throws IOException{
// 1.創建臨時文件夾
String rootPath = request.getSession().getServletContext().getRealPath("/");
System.out.println(rootPath);
String fileName = UUID.randomUUID().toString().replaceAll("-", "");
// 處理圖片信息,將圖片轉爲base64字符串
File imageFile = new File("D:\\Maple\\thanks.jpg");
Base64.Encoder base64 = Base64.getEncoder();
FileInputStream fis = new FileInputStream(imageFile);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int n;
while ((n = fis.read(b)) != -1)
{
bos.write(b, 0, n);
}
fis.close();
bos.close();
// 處理表格的數據信息
List<Map<String, Object>> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Map<String, Object> map = new HashMap<>();
map.put("nickName", "笑小楓" + i);
map.put("visitTime", DateUtil.parseDateToString(null, new Date()));
map.put("isLike", "是");
map.put("isAttention", "是");
list.add(map);
}
// 加載word中的數據信息
WordUtil word = new WordUtil();
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("title", "記得關注我喲");
dataMap.put("email", "[email protected]");
dataMap.put("name", "笑小楓");
dataMap.put("createDate", "2020-11-11");
dataMap.put("pic", base64.encodeToString(bos.toByteArray()));
dataMap.put("peopleList", list);
word.createWord(dataMap, "testWord.ftl", rootPath + "/"+fileName+".doc");
File file = new File(rootPath + "/"+fileName+".doc");
InputStream fin = null;
ServletOutputStream out = null;
try {
// 調用工具類的createDoc方法生成Word文檔
fin = new FileInputStream(file);
String exportName = "測試word";
//根據瀏覽器類型處理文件名稱
String agent = request.getHeader("USER-AGENT").toLowerCase();
String firefox = "firefox";
//若是火狐
if (agent.contains(firefox)) {
exportName = new String(exportName.getBytes(StandardCharsets.UTF_8), "ISO8859-1");
} else {//其他瀏覽器
exportName = java.net.URLEncoder.encode(exportName, "UTF-8");
}
response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
// 設置瀏覽器以下載的方式處理該文件名
response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(exportName + ".doc", "UTF-8"))));
out = response.getOutputStream();
// 緩衝區
byte[] buffer = new byte[512];
int bytesToRead;
// 通過循環將讀入的Word文件的內容輸出到瀏覽器中
while ((bytesToRead = fin.read(buffer)) != -1) {
out.write(buffer, 0, bytesToRead);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fin != null) {
fin.close();
}
if (out != null) {
out.close();
}
// 刪除臨時文件
file.delete();
}
return Result.success();
}
}
測試
在瀏覽器輸入http://127.0.0.1:8003/exportWord便可以看到你的word出來了呦。
導出效果圖如下:
本文到此結束了,後續文章會陸續更新,文檔會同步在CSDN和GitHub保持同步更新。
點個關注再走唄~~~