SpringBoot 集成 FreeMarker 導出 Word 模板文件(底部附源碼)

思路解說

  1. word 模板文件(doc 或 docx 文件)另存為 xml 文件
  2. 將後綴 xml 改成 html;大部分文檔會改成 ftl(FreeMarker 的後綴名),因為 word 文件另存為 xml 文件後,xml 文件中的程式碼很亂,後面的修改會很麻煩,因為我習慣用 VSCode 編輯器,安裝 Beautify 插件後,可以自動格式化 html 程式碼,這樣有利於後面的修改
  3. 將內容用${param}替換;例:姓名:月牙墜–>姓名:${name}
  4. word 文件中的圖片是 Base64 編碼,我在這裡封裝了一個方法 imgUrl2Base64(圖片地址轉Base64編碼) top.yueyazhui.word_freemarker.util.ExportDocUtil.getImageBase64
  5. 如果想要列表(表格)內容,在 html 文件中找到單個內容,在外層加<#list favorites as favorite></#list>
    封裝導出 word 文件到客戶端的方法top.yueyazhui.word_freemarker.service.IExportDocService.exportDocToClient
    html 中引用的數據源是一個Map<String, Object>類型,所以傳遞數據的時候需要把Object類型轉成Map<String, Object>類型
    word 原文件src/main/resources/attachment/info.doc

FreeMarker 配置

#指定freemarker的模板路徑和模板的後綴
spring.freemarker.template-loader-path=classpath:/templates/
spring.freemarker.suffix=.html
# 指定字符集
spring.freemarker.charset=utf-8
# 指定是否要啟用快取
spring.freemarker.cache=false
#指定是否要暴露請求和會話屬性
spring.freemarker.expose-request-attributes=true
spring.freemarker.expose-session-attributes=true

FreeMarker 語法

<#noparse>
    <#include "./common.ftl">
</#noparse>

<#if favorite.id == 5>
    <#break>
</#if>

<#switch sex>
    <#case 1>男<#break>
    <#case 0>女<#break>
    <#default>未知
</#switch>

前端(vue)

api

import request from '@/utils/request'

export function exportDoc() {
  return request({
    url: '/export/doc/',
    method: 'get',
    responseType: 'blob'
  })
}

view

import { exportDoc } from '@/api/**'

exportDoc().then(res => {
  var fileNameEncode = res.headers['content-disposition'].split('filename=')[1]
  var fileName = decodeURIComponent(fileNameEncode)

  const blob = new Blob([res.data], {
    type: res.data.type
  })
  let link = document.createElement('a')
  link.style.display = 'none'
  let objectUrl = URL.createObjectURL(blob)
  link.href = objectUrl
  link.download = fileName
  link.click()
  URL.revokeObjectURL(objectUrl)
})

註:axios 的響應攔截器

// 二進位數據則直接返回
if (res.request.responseType === 'blob') {
  return res
}

源碼

word_freemarker