使用POI-TL实现word的下载。

前言:POI-TL(poi template language)是Word模板引擎,基于Microsoft Word模板和数据生成新的文档。前面文章提到过使用POI技术实现excel的导入导出。那么这次说下word的下载。
一、简单介绍一下poi-tl标签:
在poi-tl 1.12版本

<dependency>
  <groupId>com.deepoovegroupId>
  <artifactId>poi-tlartifactId>
  <version>1.12.1version>
dependency>

1、文本:{{text}}

  • String :文本
  • TextRenderData :有样式的文本
  • HyperlinkTextRenderData :超链接和锚点文本
  • Object :调用 toString() 方法转化为文本

对应java代码:

put("name", "张三");
put("author", new TextRenderData("000000", "张三"));
put("link", new HyperlinkTextRenderData("website", "http://www.baidu.com"));

2、图片:{{@image}}

  • String :图片url或者本地路径,默认使用图片自身尺寸
  • PictureRenderData
  • ByteArrayPictureRenderData
  • FilePictureRenderData
  • UrlPictureRenderData

对应java代码:

// 指定图片路径
put("image", "logo.png");
// svg图片
put("svg", "https://img0.baidu.com/it/u=2776854325,1960063339&fm=253&fmt=auto&app=120&f=JPEG?w=640&h=360");

// 设置图片宽高
put("image1", Pictures.ofLocal("logo.png").size(120, 120).create());

// 图片流
put("streamImg", Pictures.ofStream(new FileInputStream("logo.jpeg"), PictureType.JPEG).size(100, 120).create());

// 网络图片(注意网络耗时对系统可能的性能影响)
put("urlImg", Pictures.ofUrl("http://deepoove.com/images/icecream.png").size(100, 100).create());

// java图片
put("buffered", Pictures.ofBufferedImage(bufferImage, PictureType.PNG).size(100, 100).create());

3、表格:{{#table}}

  • TableRenderData

对应java代码:

RowRenderData row0 = Rows.of("列0", "列1", "列2").center().bgColor("4472C4").create();
RowRenderData row1 = Rows.create("没有数据", null, null);
MergeCellRule rule = MergeCellRule.builder().map(Grid.of(1, 0), Grid.of(1, 2)).build();
put("table3", Tables.of(row0, row1).mergeRule(rule).create());

4、列表:{{*list}}

  • NumberingRenderData

java对应的代码:
使用工厂 Numberings 构建列表模型。

put("list", Numberings.create("Plug-in grammar",
                    "Supports word text, pictures, table...",
                    "Not just templates"));

编号样式支持罗马字符、有序无序等,可以通过 Numberings.of(NumberingFormat) 来指定。

DECIMAL //1. 2. 3.
DECIMAL_PARENTHESES //1) 2) 3)
BULLET //● ● ●
LOWER_LETTER //a. b. c.
LOWER_ROMAN //i ⅱ ⅲ
UPPER_LETTER //A. B. C.

二、实现功能背景:
将前端展示的E-Charts图表及文字描述,生成word并下载下来。和前端商量了下参数结构,前端可以将图表转成图片的base64编码传参,那么对于后端来说不需要再生成图表,简单了很多,废话不多说,上代码:
三、相关依赖:

	(注:①poi和poi-tl不同版本之间会出现冲突②和easy-poi依赖会出现冲突)

使用POI-TL实现word的下载。_第1张图片

		<dependency>
            <groupId>com.deepoovegroupId>
            <artifactId>poi-tlartifactId>
            <version>1.8.2version>
        dependency>
        <dependency>
            <groupId>commons-iogroupId>
            <artifactId>commons-ioartifactId>
            <version>2.11.0version>
        dependency>
        <dependency>
            <groupId>org.apache.logging.log4jgroupId>
            <artifactId>log4j-apiartifactId>
            <version>2.14.1version>
        dependency>
        <dependency>
            <groupId>org.apache.poigroupId>
            <artifactId>poi-ooxmlartifactId>
            <version>5.2.2version>
        dependency>
        <dependency>
            <groupId>org.apache.poigroupId>
            <artifactId>poiartifactId>
            <version>5.2.2version>
        dependency>
        <dependency>
            <groupId>org.apache.poigroupId>
            <artifactId>poi-ooxml-schemasartifactId>
            <version>4.1.2version>
        dependency>
        <dependency>
            <groupId>org.apache.poigroupId>
            <artifactId>poi-scratchpadartifactId>
            <version>5.2.2version>
            <scope>compilescope>
        dependency>

四、模板:
根据背景分析我们只需要定义两种标签即可,word模板对应的参数。如下:
使用POI-TL实现word的下载。_第2张图片
五、参数结构:

[{
"model":"基本资料分析",
"content":[
     {
       "title":"总体kpi",
       "image":["data:image/jpeg;base64,"],
       "desc":["描述111"]
     },
      {
       "title":"体检人群分布",
       "image":["data:image/jpeg;base64,","data:image/jpeg;base64,"],
       "desc":["描述121"]
     }
]
},
{
"model":"健康总体分析",
"content":[
     {
       "image":["data:image/jpeg;base64,"],
       "desc":["描述211"]
     }
]
},
{
"model":"体检结果综合评定",
"content":[
     {
       "image":["data:image/jpeg;base64,"],
       "desc":["描述311","描述312"]
     },
     {
        "image":["data:image/jpeg;base64,"],
        "desc":["描述321"]
     }
]
}]

拆解步骤:
1、先解析base64编码住转成文件流或者转化成url。
2、根据结构拼模板key。
3、执行模板,渲染数据。
4、下载word。

六、代码:
1、解析base64编码,转成url

/**
*解析base64编码,上传到七牛云转成url
**/
public String getUrl(String base64Pic){
        try {
            BASE64Decoder decoder = new BASE64Decoder();
            //前台传base64值的时候会把base64中的+换成空格,所以需要替换回来。
            String baseValue = base64Pic.replaceAll(" ", "+");
            //去除base64中无用的部分
            byte[] bytes = decoder.decodeBuffer(baseValue.replace("data:image/jpeg;base64,", ""));
            Map<String, Object> map = QiNiuUtil.byteUpload(bytes);
            String httpPicUrl = (String) map.get("httpPicUrl");
            return httpPicUrl;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

2、拼接模板对应参数值

/**
*拼参数
**/
public void putParams(List<WordRequestDTO> wordRequestLists) {
        try {
            // Word文档数据格式封装
            Map<String, Object> result=new HashMap<>();
            for (int i=1;i<=wordRequestLists.size();i++){
                WordRequestDTO wordRequestDTO = wordRequestLists.get(i-1);
                result.put("model"+i,new TextRenderData(wordRequestDTO.getModel()));
                List<ContentDTO> contentLists = wordRequestDTO.getContent();
                for (int j=1;j<=contentLists.size();j++){
                    ContentDTO content = contentLists.get(j-1);
                    if (!ObjectUtils.isEmpty(content.getTitle())){
                        result.put("title"+i+j,new TextRenderData(content.getTitle()));
                    }
                    List<String> image = content.getImage();
                    if (!CollectionUtils.isEmpty(image)){
                        for (int k=1;k<=image.size();k++){
                            result.put("image"+i+j+k,new PictureRenderData(600, 350, ".jpg",BytePictureUtils.getUrlByteArray(getUrl(image.get(k-1)))));
                        }
                    }
                    List<String> desc = content.getDesc();
                    if (!CollectionUtils.isEmpty(desc)){
                        for (int k=1;k<=desc.size();k++){
                            result.put("desc"+i+j+k,new TextRenderData(desc.get(k-1)));
                        }
                    }
                }
            }
            return result;
   		}catch (Exception e) {
            e.printStackTrace();
        }
        return null;
   	}	

3、执行模板,渲染数据(path:模板.docx的路径)

/**
*执行模板,渲染数据
**/
public String getUrl(String path){
    XWPFTemplate template = XWPFTemplate.compile(new File(path));
    template = template.render(result);
 }

4、下载wrod

public  void downloadServlet(XWPFTemplate template, HttpServletResponse response) {
        try {
            response.setHeader("Content-disposition", "attachment;filename=" + new String("团检".getBytes("gb2312"), "ISO8859-1") + ".docx");
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/octet-stream");
            ServletOutputStream out = response.getOutputStream();
            template.write(out);
            out.flush();
            template.close();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

七、postman接口测试通过,下载的word内容如下图:
使用POI-TL实现word的下载。_第3张图片

除了提前预制word模板,使用 XWPFTemplate.create 在无需模板的情况下创建文档,可以充分利用poi-tl友好的API来生成文档元素。详见:http://deepoove.com/poi-tl/

你可能感兴趣的:(POI,word,java,开发语言)