Java如何向Word模板中插入Base64图片和数据信息

 更新时间:2024年07月03日 08:41:44   作者:霁月清风与谁同  
这篇文章主要介绍了Java如何向Word模板中插入Base64图片和数据信息问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

需求

在服务端提前准备好Word模板文件,并在用户请求接口时服务端动态获取图片。

数据等信息插入到模板当中,然后返回包含数据信息的Word文件流。

一、准备模板文件

在需要插入图片的地方使用:{{@参数名}},文本信息使用:{{参数名}},进行占位,占位格式将会被保留,经过处理后格式不变

将准备好的模板文件放在resources目录下

blog.csdnimg.cn/direct/6d1474091083427483e11ea71e25ef51.png)

二、引入Poi-tl、Apache POI依赖

poi-tl(poi template language)是Word模板引擎,基于Apache POI,提供更友好的API,使用起来更加简单

版本对应关系参考Poi-tl官网

<!--    替换自己使用的版本    -->
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>4.1.*</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>4.1.*</version>
</dependency>
<!--    Word模板引擎    -->
<dependency>
	<groupId>com.deepoove</groupId>
	<artifactId>poi-tl</artifactId>
	<version>1.7.*</version>
</dependency>

三、创建实体类(用于保存向Word中写入的数据)

参数名必须同Word模板中的参数名称保持一致

import com.deepoove.poi.data.PictureRenderData;

@Data
public class DownloadDate {
    //图片使用PictureRenderData类型
    private PictureRenderData image;
    private String name;
    private String a;
    private String b;
    private String c;
    private String d;
    private String e;
    private String f;
    private String g;
    private String h;
    private String i;
}

四、实现Service接口

public interface DownloadService {
     void download(HttpServletResponse response, DownloadDTO downloadDTO) throws IOException;
}
@Service
@Slf4j
public class DownloadServiceImpl implements DownloadService {

    @Resource
    //远程调用服务
    private FeignService feignService;
    
    @Override
    public void download(HttpServletResponse response, DownloadDTO downloadDTO) throws IOException {BufferedImage、字节数组),Base64可以转字节数组后使用
    	//通过调用其它接口获取待写入的数据信息
    	WordData wordData = feignService.getData(downloadDTO);
        /** 
        * 图片可以是多种格式------------------------
        * 图片路径:PictureRenderData(int width, int height, String path)
        * File:PictureRenderData(int width, int height, File picture)
        * InputStream:PictureRenderData(int width, int height, String format, InputStream input)
        * BufferedImage:PictureRenderData(int width, int height, String format, BufferedImage image)
        * 字节数组:PictureRenderData(int width, int height, String format, byte[] data)
        * Base64可以转字节数组后使用
        */

        //以Base64为例,先获取图片的Base64编码(wordData.getImg是原始图片Base64数据)
        String base64ImageData = wordData.getImg.substring(data.indexOf(",") + 1);
        //获取图片类型
        String format = getBase64Type(base64ImageData);
        // 将base64数据转为字节数组
        byte[] imageBytes = Base64.getDecoder().decode(base64ImageData);
        // 将字节数组包装成PictureRenderData
        PictureRenderData pictureRenderData = new PictureRenderData(690,530,format,imageBytes);
        //待写入Word的数据
        DownloadDate downloadDate = new DownloadDate();
        //图片信息
        downloadDate.setImage(pictureRenderData);
        //其它信息
        downloadDate.setName(wordData.getName());
        //...
        XWPFTemplate template = null;
        BufferedOutputStream bufferedOutputStream = null;
        ServletOutputStream outputStream = null;
        try {
        	/** 
        	* 该方法会导致在部分环境中资源找不到的情况,不推荐使用
        	*/
            //获得resource路径+模板路径
            //String path = Objects.requireNonNull(Thread.currentThread().getContextClassLoader().getResource("")).getPath() + "word/template.docx";
            // 读取Word模板
            //FileInputStream templateInputStream = new FileInputStream(path);
            // 模板绑定数据
            //template = XWPFTemplate.compile(templateInputStream).render(imageDownloadDate);
            
            // 从资源中加载Word模板
            try (InputStream templateInputStream = getClass().getClassLoader().getResourceAsStream("word/template.docx")) {
                if (templateInputStream != null) {
                    // 模板绑定数据
                    template = XWPFTemplate.compile(templateInputStream).render(imageDownloadDate);
                } else {
                    // 处理模板资源未找到的情况
                    log.error("Word模板资源未找到");
                    response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                    return;
                }
            }
            //文件名
            String encodedFileName = URLEncoder.encode(System.currentTimeMillis()+"", "utf-8");
            //设置响应信息
            response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName + ".docx");
            response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
            response.setCharacterEncoding("utf-8");
            outputStream = response.getOutputStream();
            bufferedOutputStream = new BufferedOutputStream(outputStream);
            template.write(bufferedOutputStream);
            //清空流
            bufferedOutputStream.flush();
            outputStream.flush();
        } catch (Exception e) {
            log.info(e.getMessage());
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        } finally {
            //关闭资源
            PoitlIOUtils.closeQuietlyMulti(template, bufferedOutputStream, outputStream);
        }
    }
    
    //根据base64编码获取图片格式信息
    private String getBase64Type(String base64) {
        byte[] b = Base64.getDecoder().decode(base64);
        String type = ".png";
        if (0x424D == ((b[0] & 0xff) << 8 | (b[1] & 0xff))) {
            type = ".bmp";
        } else if (0x8950 == ((b[0] & 0xff) << 8 | (b[1] & 0xff))) {
            type = ".png";
        } else if (0xFFD8 == ((b[0] & 0xff) << 8 | (b[1] & 0xff))) {
            type = ".jpg";
        } else if (0x49492A00 == ((b[0] & 0xff) << 24 | (b[1] & 0xff) << 16 | (b[2] & 0xff) << 8 | (b[3] & 0xff))) {
            type = ".tif";
        }
        return type;
    }

}

五、Controller层实现

@RestController
@RequestMapping("/test")
@Api(tags = "获取商品图片")
public class GetImageController {

    @Resource
    DownloadService downloadService;

    @PostMapping("/download")
    @ApiOperation(value = "下载Word")
    void download(HttpServletResponse response,@RequestBody DownloadDTO downloadDTO) throws IOException {
        //鉴权或其它处理
        //....
        downloadService.download(response,downloadDTO);
    }
    
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。 

相关文章

  • PageHelper插件实现一对多查询时的分页问题

    PageHelper插件实现一对多查询时的分页问题

    这篇文章主要介绍了PageHelper插件实现一对多查询时的分页问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • 图文精讲java常见分布式事务理论与解决方案

    图文精讲java常见分布式事务理论与解决方案

    对于分布式系统,最简单的理解就是一堆机器对外提供服务,相比单体服务,它可以承受更高的负载,但是分布式系统也带了一系列问题,今天带大家搞懂和分布式相关的常见理论和解决方案
    2021-11-11
  • mybatis初始化SqlSessionFactory失败的几个原因分析

    mybatis初始化SqlSessionFactory失败的几个原因分析

    这篇文章主要介绍了mybatis初始化SqlSessionFactory失败的几个原因分析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Java中final关键字的深入探究

    Java中final关键字的深入探究

    这篇文章主要给大家介绍了关于Java中final关键字的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • 详解关于SpringBoot的外部化配置使用记录

    详解关于SpringBoot的外部化配置使用记录

    这篇文章主要介绍了详解关于SpringBoot的外部化配置使用记录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • Java泛型中<?>和<T>的区别浅析

    Java泛型中<?>和<T>的区别浅析

    <T>和<?>的区别 <T>是参数类型,常常用于泛型类或泛型方法的定义,下面这篇文章主要给大家介绍了关于Java泛型中<?>和<T>区别的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-12-12
  • 一文读懂Spring Bean的生命周期

    一文读懂Spring Bean的生命周期

    今天我们来说一说 Spring Bean 的生命周期,小伙伴们应该在面试中经常遇到,这是正常现象,本文让更多的小伙伴们可以轻松的读懂 Spring Bean 的生命周期
    2023-03-03
  • Spring中配置和读取多个Properties文件的方式方法

    Spring中配置和读取多个Properties文件的方式方法

    本篇文章主要介绍了Spring中配置和读取多个Properties文件的方式方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-04-04
  • JAVA8 stream中三个参数的reduce方法对List进行分组统计操作

    JAVA8 stream中三个参数的reduce方法对List进行分组统计操作

    这篇文章主要介绍了JAVA8 stream中三个参数的reduce方法对List进行分组统计操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • 大厂禁止SpringBoot在项目使用Tomcat容器原理解析

    大厂禁止SpringBoot在项目使用Tomcat容器原理解析

    这篇文章主要为大家介绍了大厂禁止SpringBoot在项目使用Tomcat原理解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07

最新评论