使用freemarker 模块,导出word文档(多图带图名导出)

由于项目需要,要做一个导出word文档。导出的文档里需要有多张图片和文字。 

  1.     先找一个word文档做模板。我的模板里就只用图片和图片对应的名字。图片需要先在模板文档中随便插入一张图片,而图片对应的名字用${photoTitle}来表示(photoTitle是我给图名这个变量的名字)。如下图
  2. 之后将模板文档保存为xml文件,像这样。之后再将文件后缀改成ftl,即skrd1.ftl。
  3. 打开ftl的模板文件,找到文档里赛的那个图片,在ftl里显示的是图片的base64编码。

     

将那一串编码改成${photoCode}(使用个占位符,photoCode是我对那串编码起的名字) 

    4. 多张图片的话,需要对图片那里使用freemarker的一个list循环<#list photoList as ph></#list>,我用idea打开了ftl模板文件,方便查看。如图。添加list的位置找了好久,我是需要图片和图名一起循环添加的,所以就把${photoCode}和${photoTitle}的范围一起放在list中,photoList是循环list的名字,ph是别名。(注意,多张图片时需要修改<w:binData w:name="..">和<v:imagedata src="..">这两个的内容,如果是固定的,那么就只会显示第一张图片。可以按照下图来修改。)

我的ftl模板就配置了这么多。接下来就是代码了

使用freemarker先引入依赖

<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.23</version>
</dependency>

 这是我后端接口,fileCode是前端将多张图片编码后以逗号隔开的字符串。最后文件就是直接被下载下来的,不会产生中间文件。

@GetMapping(value = "/export", produces = "application/json;charset=utf-8")
public ResponseEntity<byte[]> exportWord(String fileCode) {
    return fileService.exportWord(fileCode);
}
@Override
public ResponseEntity<byte[]> exportWord(String fileCode) {
    /** 拆分图片编码 */
    List<String> imageCodeList = getImageCodeList(fileCode);
    /** 组装模块数据 */
    Map<String, Object> dataMap = FileUtil.getTemplateMap(imageCodeList);

    /** word文档导出名字 */
    //todo  导出word文档的命名  ---待定
    String fileName = "123.docx";

    byte[] b = null;
    try {
        b = FileUtil.export(dataMap);
    } catch (Exception e) {
        e.printStackTrace();
    }
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    try {
        headers.setContentDispositionFormData("attachment", new String(fileName.getBytes("utf-8"), "ISO_8859_1"));
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(b, headers, HttpStatus.OK);
    return responseEntity;
}
PACKAGE_PATH是我模板所在的目录,TEMPLATE是模板名称。dataMap是把模板中需要的数据组装进去的map,即使是多张图片用了list,最后用的也只是一个map。map中放的list的名字需要和模板中list的名字相同,我这里都是photoList,别名无所谓。
public class FileUtil {
    /**
     * 模板所在目录
     */
    private static final String PACKAGE_PATH = "src/main/resources/templates/";
    /**
     * 模板名称
     */
    private static final String TEMPLATE = "skrdModel.ftl";

    public static byte[] export(Map<String, Object> dataMap) throws IOException {
        /** 使用freemarker中的Configuration,处理模板 */
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_21);
        configuration.setDefaultEncoding("utf-8");
        /** 加载模板 */
        configuration.setDirectoryForTemplateLoading(new File(PACKAGE_PATH));
        /** 引用模板 */
        Template t = configuration.getTemplate(TEMPLATE);

        File outFile = new File(TEMPLATE);
        Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"));
        try {
            /** 将dataMap中的数据填入模板中 */
            t.process(dataMap, writer);
        } catch (TemplateException e) {
            e.printStackTrace();
        }
        writer.close();
        return FileUtils.readFileToByteArray(outFile);
    }

    /**
     * 将图片的base64编码,以及图片的名称放入map中
     *
     * @return
     */
    public static Map<String, Object> getTemplateMap(List<String> imageCodeList) {
        Map<String, Object> dataMap = new HashMap<>(16);
        List<Map<String, Object>> photo = new ArrayList<>();
        for (String imageCode : imageCodeList) {
            Map<String, Object> ph = new HashMap<>(16);

            /** 图表的名称 */
            //todo 图表名称 --待定
            ph.put("photoTitle", "插入的图");
            /** 图片的base64编码 */
            //todo  需要插入的图片的base64编码
            ph.put("photoCode", imageCode);

            photo.add(ph);
        }
        dataMap.put("photoList", photo);
        return dataMap;
    }
}

 

以上便是我导出的过程。请多指教

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值