SpringBoot集成文件-如何基于POI-tl和word模板导出庞大的Word文件?

前文我们介绍了通过Apache POI通过来导出word的例子;那如果是word模板方式,有没有开源库通过模板方式导出word呢?poi-tl是一个基于Apache POI的Word模板引擎,也是一个免费开源的Java类库,你可以非常方便的加入到你的项目中,并且拥有着让人喜悦的特性。本文主要介绍通过SpringBoot集成poi-tl实现模板方式的Word导出功能。

知识准备

需要理解文件上传和下载的常见场景和技术手段。@pdai

什么是poi-tl

如下内容来源于,poi-tl官网

poi-tl(poi template language)是Word模板引擎,使用Word模板和数据创建很棒的Word文档。

优势:

SpringBoot集成文件-如何基于POI-tl和word模板导出庞大的Word文件?

它还支持自定义插件,如下是官网代码仓库支持的特性

poi-tl supports custom functions (plug-ins), functions can be executed anywhere in the Word template, do anything anywhere in the document is the goal of poi-tl.

Feature Description ✅ Text Render the tag as text ✅ Picture Render the tag as a picture ✅ Table Render the tag as a table ✅ Numbering Render the tag as a numbering ✅ Chart Bar chart (3D bar chart), column chart (3D column chart), area chart (3D area chart), line chart (3D line chart), radar chart, pie chart (3D pie Figure) and other chart rendering ✅ If Condition Hide or display certain document content (including text, paragraphs, pictures, tables, lists, charts, etc.) according to conditions ✅ Foreach Loop Loop through certain document content (including text, paragraphs, pictures, tables, lists, charts, etc.) according to the collection ✅ Loop table row Loop to copy a row of the rendered table ✅ Loop table column Loop copy and render a column of the table ✅ Loop ordered list Support the loop of ordered list, and support multi-level list at the same time ✅ Highlight code Word highlighting of code blocks, supporting 26 languages ​​and hundreds of coloring styles ✅ Markdown Convert Markdown to a word document ✅ Word attachment Insert attachment in Word ✅ Word Comments Complete support comment, create comment, modify comment, etc. ✅ Word SDT Complete support structured document tag ✅ Textbox Tag support in text box ✅ Picture replacement Replace the original picture with another picture ✅ bookmarks, anchors, hyperlinks Support setting bookmarks, anchors and hyperlinks in documents ✅ Expression Language Fully supports SpringEL expressions and can extend more expressions: OGNL, MVEL… ✅ Style The template is the style, and the code can also set the style ✅ Template nesting The template contains sub-templates, and the sub-templates then contain sub-templates ✅ Merge Word merge Merge, you can also merge in the specified position ✅ custom functions (plug-ins) Plug-in design, execute function anywhere in the document

poi-tl的TDO模式

TDO模式:Template + data-model = output

以官网的例子为例:

XWPFTemplate template = XWPFTemplate.compile("template.docx").render(
  new HashMap(){{
    put("title", "Hi, poi-tl Word模板引擎");
}});
template.writeAndClose(new FileOutputStream("output.docx"));
  • compile 编译模板 – Template
  • render 渲染数据 – data-model
  • write 输出到流 – output

Template:模板

模板是Docx格式的Word文档,你可以使用Microsoft office、WPS Office、Pages等任何你喜欢的软件制作模板,也可以使用Apache POI代码来生成模板。

所有的标签都是以 {{开头,以 }}结尾,标签可以出现在任何位置,包括页眉,页脚,表格内部,文本框等,表格布局可以设计出很多优秀专业的文档,推荐使用表格布局。

poi-tl模板遵循”所见即所得”的设计,模板和标签的样式会被完全保留。

Data-model:数据

数据类似于哈希或者字典,可以是Map结构(key是标签名称):

Map data = new HashMap<>();
data.put("name", "Sayi");
data.put("start_time", "2019-08-04");

可以是对象(属性名是标签名称):

public class Data {
  private String name;
  private String startTime;
  private Author author;
}

数据可以是树结构,每级之间用点来分隔开,比如 { {author.name} }标签对应的数据是author对象的name属性值。

Word模板不是由简单的文本表示,所以在渲染图片、表格等元素时提供了数据模型,它们都实现了接口RenderData,比如图片数据模型PictureRenderData包含图片路径、宽、高三个属性。

Output:输出

以流的方式进行输出:

template.write(OutputStream stream);

可以写到任意输出流中,比如文件流:

template.write(new FileOutputStream("output.docx"));

比如网络流:

response.setContentType("application/octet-stream");
response.setHeader("Content-disposition","attachment;filename=\""+"out_template.docx"+"\"");

// HttpServletResponse response
OutputStream out = response.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(out);
template.write(bos);
bos.flush();
out.flush();
PoitlIOUtils.closeQuietlyMulti(template, bos, out); // 最后不要忘记关闭这些流。

实现案例

这里展示SpringBoot集成poi-tl基于word模板导出Word, 以及导出markdown为word的例子。

Pom依赖

引入poi的依赖包

基础的包:


    com.deepoove
    poi-tl
    1.12.0

插件的包如下,比如highlight,markdown包


    com.deepoove
    poi-tl-plugin-highlight
    1.0.0

    com.deepoove
    poi-tl-plugin-markdown
    1.0.3

导出基于template的word

controller中的方法

@ApiOperation("Download Word")
@GetMapping("/word/download")
public void download(HttpServletResponse response) {
    try {
        XWPFTemplate document = userService.generateWordXWPFTemplate();
        response.reset();
        response.setContentType("application/octet-stream");
        response.setHeader("Content-disposition",
                "attachment;filename=user_word_" + System.currentTimeMillis() + ".docx");
        OutputStream os = response.getOutputStream();
        document.write(os);
        os.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Service中的实际方法

@Override
public XWPFTemplate generateWordXWPFTemplate() throws IOException {
    Map content = new HashMap<>();
    content.put("title", "Java 全栈知识体系");
    content.put("author", "pdai");
    content.put("site", new HyperlinkTextRenderData("https://pdai.tech", "https://pdai.tech"));

    content.put("poiText", "Apache POI 是创建和维护操作各种符合Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE2)的Java API。用它可以使用Java读取和创建,修改MS Excel文件.而且,还可以使用Java读取和创建MS Word和MSPowerPoint文件。更多请参考[官方文档](https://poi.apache.org/index.html)");

    content.put("poiText2", "生成xls和xlsx有什么区别?POI对Excel中的对象的封装对应关系?");
    content.put("poiList", Numberings.create("excel03只能打开xls格式,无法直接打开xlsx格式",
            "xls只有65536行、256列; xlsx可以有1048576行、16384列",
            "xls占用空间大, xlsx占用空间小,运算速度也会快一点"));

    RowRenderData headRow = Rows.of("ID", "Name", "Email", "TEL", "Description").textColor("FFFFFF")
            .bgColor("4472C4").center().create();
    TableRenderData table = Tables.create(headRow);
    getUserList()
            .forEach(a -> table.addRow(Rows.create(a.getId() + "", a.getUserName(), a.getEmail(), a.getPhoneNumber() + "", a.getDescription())));
    content.put("poiTable", table);

    Resource resource = new ClassPathResource("pdai-guli.png");
    content.put("poiImage", Pictures.ofStream(new FileInputStream(resource.getFile())).create());

    return XWPFTemplate.compile(new ClassPathResource("poi-tl-template.docx").getFile()).render(content);
}

private List getUserList() {
    List userList = new ArrayList<>();
    for (int i = 0; i < 5; i++) {
        userList.add(User.builder()
                .id(Long.parseLong(i + "")).userName("pdai" + i).email("pdai@pdai.tech" + i).phoneNumber(121231231231L)
                .description("hello world" + i)
                .build());
    }
    return userList;
}

准备模板

SpringBoot集成文件-如何基于POI-tl和word模板导出庞大的Word文件?

导出word

SpringBoot集成文件-如何基于POI-tl和word模板导出庞大的Word文件?

导出markdown为word

controller中的方法

@ApiOperation("Download Word based on markdown")
@GetMapping("/word/downloadMD")
public void downloadMD(HttpServletResponse response) {
    try {
        XWPFTemplate document = userService.generateWordXWPFTemplateMD();
        response.reset();
        response.setContentType("application/octet-stream");
        response.setHeader("Content-disposition",
                "attachment;filename=user_word_" + System.currentTimeMillis() + ".docx");
        OutputStream os = response.getOutputStream();
        document.write(os);
        os.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Service中实现的方法


@Override
public XWPFTemplate generateWordXWPFTemplateMD() throws IOException {
    MarkdownRenderData code = new MarkdownRenderData();

    Resource resource = new ClassPathResource("test.md");
    code.setMarkdown(new String(Files.readAllBytes(resource.getFile().toPath())));
    code.setStyle(MarkdownStyle.newStyle());

    Map data = new HashMap<>();
    data.put("md", code);

    Configure config = Configure.builder().bind("md", new MarkdownRenderPolicy()).build();

    return XWPFTemplate.compile(new ClassPathResource("markdown_template.docx").getFile(), config).render(data);
}

准备模板

SpringBoot集成文件-如何基于POI-tl和word模板导出庞大的Word文件?

导出word

SpringBoot集成文件-如何基于POI-tl和word模板导出庞大的Word文件?

示例源码

https://github.com/realpdai/tech-pdai-spring-demos

参考文章

http://deepoove.com/poi-tl/

更多内容

告别碎片化学习,无套路一站式体系化学习后端开发: Java 全栈知识体系(https://pdai.tech)

Original: https://www.cnblogs.com/pengdai/p/16537534.html
Author: pdai
Title: SpringBoot集成文件-如何基于POI-tl和word模板导出庞大的Word文件?

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/575566/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Elasticsearch高级检索之使用单个字母数字进行分词N-gram tokenizer(不区分大小写)【实战篇】

    一、前言 小编最近在做到一个检索相关的需求,要求按照一个字段的每个字母或者数字进行检索,如果是不设置分词规则的话,英文是按照单词来进行分词的。 小编以7.6.0版本做的功能哈,大家…

    Java 2023年6月15日
    087
  • 通过系统数据库获取用户所有数据库、表、存储过程、视图

    –设置sql 可以获取实例名称 sp_configure ‘xp_cmdshell’ , 1 ; reconfigure ; –获取…

    Java 2023年6月5日
    075
  • Mysql 的Innodb引擎和Myisam数据结构和区别

    先大体看一下MySQL的SQL layer层的一个架构流程: 对一些关键模块做一下简单的描述: 初始模块:初始一些参数,比如初始myinit配置文件(在安装的根目录下)里的一些参数…

    Java 2023年6月14日
    074
  • Redis核心设计原理(深入底层C源码)

    Redis 基本特性 非关系型的键值对数据库,可以根据键以O(1) 的时间复杂度取出或插入关联值 Redis 的数据是存在内存中的 键值对中键的类型可以是字符串,整型,浮点型等,且…

    Java 2023年6月16日
    085
  • q命令-用SQL分析文本文件

    原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 在Linux上分析文本文件时,一般会使用到grep、sed、awk、sort、uniq等命令,但这些…

    Java 2023年6月7日
    084
  • Java:JVM基础——非堆部分(Java8)

    PS:现在普遍都是 Java8 和 Java11 了,我不打算写 Java8 之前的了,本文出现的虚拟机都是 HotSpot 虚拟机 1、 JVM 内存结构图 2、 Java Vi…

    Java 2023年6月7日
    057
  • CAS原子性操作

    CAS原理解析 1、CAS基本概念 CAS(Compare And Swap)也叫做比较与交换,是一种无锁原子算法,映射到操作系统就是一条cmpxchg硬件汇编指令,通过硬件命令保…

    Java 2023年6月5日
    079
  • 编译原理的文法和语言总结与梳理

    梳理文法和语言的内容,理解与总结。 我们都知道,一种语言必定他的文法去描述,它的完整定义包括语法和语义两个方面。语言和语法是指一组规则,用它可以形成和产生一个合适的程序。目前广泛使…

    Java 2023年6月7日
    093
  • springboot定时任务线程阻塞踩坑

    场景描述 在使用 Springboot整合定时任务,发现当某个定时任务执行出现执行时间过长的情况时会阻塞其他定时任务的执行。 问题定位 后续通过翻查 Springboot的文档以及…

    Java 2023年5月30日
    0108
  • @Aspect一直无法自动使用的原因

    使用注解实现AOP的时候遇见了一个问题 org.aspectj aspectjweaver 1.9.6 runtime 从网上拉下来的aspectj依赖没注意带了一个 <sc…

    Java 2023年6月15日
    081
  • 【翻译】Spring Security抛弃了WebSecurityConfigurerAdapter

    作者:ELEFTHERIA STEIN-KOUSATHANA 发表日期:2022年2月21日 在Spring Security 5.7.0-M2,我们弃用了 WebSecurity…

    Java 2023年6月6日
    097
  • 基于Python豆瓣自动化测试【2】

    —— Pytest基础使用教程【2】 从测试报告说起 承接上一篇中最后的测试结果图,使用过的pytest-html 插件原生态的报告的话。可能会发现 内容样式都有些不同。其实是做了…

    Java 2023年6月15日
    076
  • Spring/Spring MVC/MyBatis整合详解

    本文引用自:《Java EE企业级应用开发教程》 由于Spring MVC只是Spring框架中的一个模块,所以Spring MVC与Spring之间不存在整合的问题,只需要引入相…

    Java 2023年5月30日
    078
  • Java基础语法(二)

    Java基础语法(二) 合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。 ——《道德经》 Java基础语法(二) – 十、用户交互 Scanner 类(引用…

    Java 2023年6月9日
    069
  • 网络编程(TCP协议)

    TCP协议发送数据 A:创建Socket对象—利用Socket对象 B:获取输出流,写数据 C:释放资源 TCP协议接受数据 A:创建Socket接受对象 B:监听客户…

    Java 2023年6月5日
    088
  • java学习之spirng的aop

    AOP技术 什么是AOP技术:在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一…

    Java 2023年6月13日
    073
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球