思路解说

  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

最新文章

  1. yii2 随笔
  2. ant的安装及项目的发布
  3. 【集合框架】Java集合框架综述
  4. ListView中itemz中控件的点击事件和条目点击事件冲突
  5. tcp timestamp
  6. C++定义全局变量/常量几种方法的区别
  7. 页面所有的button绑定同一个事件,点击不同的button赋值不同
  8. PHP 读json文件并转php配置文件
  9. R 语言DataFrame 排序
  10. Delphi 记事本 TMemo
  11. 使用strace追踪多个进程
  12. 关于单链表的增删改查方法的递归实现(JAVA语言实现)
  13. Java设计模式总结
  14. Buaa菜鸡从今天好好学打码,好好学数学,好好学英语,好好打篮球,好好锻炼,好好吃饭,好好... 好好找女朋友!
  15. 使用DataContext和ItemsSource将数据源绑定到ListView上的区别
  16. 一块移动硬盘怎样兼容Mac和Windows系统,并且可以在time machine上使用
  17. The file left unchanged.
  18. 干货分享 超炫丽的HTML5/jQuery应用及代码
  19. TensorFlow上实践基于自编码的One Class Learning
  20. [Vue warn]: Invalid prop: custom validator check failed for prop &quot;xxx&quot;.问题

热门文章

  1. 难对齐、难保障、难管理?一文了解字节跳动如何解决数据SLA治理难题
  2. Java异常处理最佳实践
  3. Maven生成可以直接执行的jar包
  4. linux篇-Centos7jdk安装
  5. 103_Power Pivot 透视表中空白标签处理及百分比
  6. Python数据分析--Numpy常用函数介绍(2)
  7. 没错,就是Access-Control-Allow-Origin,跨域
  8. Linux系统下运行.sh文件
  9. USB机械键盘改蓝牙键盘
  10. docker 操作 记录