JAVA实现向Word模板中插入Base64图片和数据信息

目录

    • 需求
    • 一、准备模板文件
    • 二、引入Poi-tl、Apache POI依赖
    • 三、创建实体类(用于保存向Word中写入的数据)
    • 四、实现Service接口
    • 五、Controller层实现

需求

在服务端提前准备好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);
    }
    
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/333713.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构图算法

算法就要多练,我在国庆节放假的时间编写了图的算法题,写完让我受益匪浅,希望可以帮助到大家. 文章目录 前言 一、图的数据结构 1.图的邻接表数据结构定义 2.图的邻接矩阵的存储形式 二、邻接表建立图代码 三、邻接表删除边(基本操作考试不考) 四、邻接表删除顶点及销毁整…

【LLM】Prompt微调

Prompt 在机器学习中&#xff0c;Prompt通常指的是一种生成模型的输入方式。生成模型可以接收一个Prompt作为输入&#xff0c;并生成与该输入相对应的输出。Prompt可以是一段文本、一个问题或者一个片段&#xff0c;用于指导生成模型生成相应的响应、续写文本等。 Prompt优化…

.pings勒索病毒的无声侵袭:保护你的数据财产免受.pings的侵害

尊敬的读者&#xff1a; 在数字时代&#xff0c;网络犯罪者不断推陈出新&#xff0c;而.pings勒索病毒则是一种极富威胁的加密型恶意软件。本文将深入探讨.pings勒索病毒的攻击方式&#xff0c;为您提供从数据恢复到全面预防的完整指南&#xff0c;帮助您有效对抗这一威胁。如…

安全帽识别:智能监控新趋势

在现代工业安全领域&#xff0c;安全帽识别技术已成为一项关键的创新。这项技术通过智能监控系统确保工作人员在危险环境中佩戴安全帽&#xff0c;显著提升了工作场所的安全标准。本文将探讨这一技术的工作原理、应用前景及其在现代工业中的重要性。 安全帽识别的工作机制 安全…

【漏洞攻击之文件上传条件竞争】

漏洞攻击之文件上传条件竞争 wzsc_文件上传漏洞现象与分析思路编写攻击脚本和重放措施中国蚁剑拿flag wzsc_文件上传 漏洞现象与分析 只有一个upload前端标签元素&#xff0c;并且上传任意文件都会跳转到upload.php页面&#xff0c;判定是一个apache容器&#xff0c;开始扫描…

什么是车载信息娱乐系统和集成驾驶舱

什么是车载信息娱乐系统(IVI)? “车载信息娱乐(IVI)”通过向驾驶员和乘客提供信息和娱乐&#xff0c;为驾驶提供便利和舒适。为了理解这个概念&#xff0c;有必要知道“信息娱乐”的含义。“信息娱乐”是这个市场中使用的一个词&#xff0c;它结合了“信息”和“娱乐”两个词…

「达摩院MindOpt」优化形状切割问题(MILP)

1. 形状切割问题 在制造业&#xff0c;高效地利用材料不仅是节约成本的重要环节&#xff0c;也是可持续发展的关键因素。无论是在金属加工、家具制造还是纺织品生产中&#xff0c;原材料的有效利用都直接影响了整体效率和环境影响。 形状切割问题&#xff08;Shape Cutting o…

区域入侵检测AI边缘计算智能分析网关V4如何通过ssh进行服务器远程运维

智能分析网关V4是一款高性能、低功耗的AI边缘计算硬件设备&#xff0c;它采用了BM1684芯片&#xff0c;集成高性能8核ARM A53&#xff0c;主频高达2.3GHz&#xff0c;并且INT8峰值算力高达17.6Tops&#xff0c;FB32高精度算力达到2.2T&#xff0c;每个摄像头可同时配置3种算法&…

万户 ezOFFICE wf_printnum.jsp SQL注入漏洞复现

0x01 产品简介 万户OA ezoffice是万户网络协同办公产品多年来一直将主要精力致力于中高端市场的一款OA协同办公软件产品,统一的基础管理平台,实现用户数据统一管理、权限统一分配、身份统一认证。统一规划门户网站群和协同办公平台,将外网信息维护、客户服务、互动交流和日…

VUE--插槽slot(将父级的模块片段插入到子级中)

组件可以接收任意类型的JS值作为props&#xff0c;但我们想要为子组件传递一些模板片段&#xff0c;并在子组件中进行渲染时&#xff0c;此时可以采用插槽slot来实现 简单来说&#xff0c;插槽时组件内留一个或多个插槽的位置&#xff0c;供组件传递对应的模板代码&#xff08;…

深入解析与实践:Ajax异步请求在Web开发中的应用指南

一、概述 1、定义 ​ Ajax&#xff08;Asynchronous JavaScript and XML&#xff09;异步请求是现代Web开发中不可或缺的技术组件&#xff0c;它允许网页在不刷新整个页面的情况下从服务器获取并更新数据&#xff0c;从而实现动态、流畅的交互体验。 2、异步和同步 浏览器访…

目标文献分析方法

如何正确选题&#xff1f; 不仅仅是题目&#xff0c;而是研究工作的起步选题步骤&#xff1f; 发现问题选择方向调查研究分析论证确定选题 中国知网 深度学习方向词 1检索&#xff1a;深度学习 医疗影像 1 发表时间要最新 2 显示50个&#xff0c;全选 3 导出文献格式Ref 4 导…

无法打开浏览器开发者工具的可能解决方法

网页地址: https://jx.xyflv.cc/?url视频地址url 我在抖音里面抓了一个视频地址, 获取到响应的json数据, 找到里面的视频地址信息 这个网站很好用: https://www.jsont.run/ 可以使用js语法对json对象操作, 找到所有视频的url地址 打开网页: https://jx.xyflv.cc/?urlhttps:…

最推荐的视频播放器——PotPlayer

PotPlayer&#xff0c;是The KMPlayer的原作者姜勇囍进入Daum公司后的新一代作品&#xff0c;目前仍有更新。由于采用Delphi编译程式的KMPlayer有一些弊端&#xff0c;姜勇囍为改进播放器本身的一些效能而重新用VC进行构架。 除了支持3D视频外&#xff0c;PotPlayer还覆盖支持…

MetaGPT-打卡-day2,MetaGPT框架组件学习

文章目录 Agent组件实现一个单动作的Agent实现一个多动作的Agent技术文档生成助手其他尝试 今天是第二天的打卡~昨天是关于一些概念的大杂烩&#xff0c;今天的话&#xff0c;就来到了Hello World环节。 从单个Agnet到多个Agent&#xff0c;再到组合更复杂的工作流来解决问题。…

分类预测 | Matlab实现CS-SVM布谷鸟算法优化支持向量机的数据分类预测

分类预测 | Matlab实现CS-SVM布谷鸟算法优化支持向量机的数据分类预测 目录 分类预测 | Matlab实现CS-SVM布谷鸟算法优化支持向量机的数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现CS-SVM布谷鸟算法优化支持向量机的数据分类预测。 2.自带数据…

均线和布林线这样的关系,WeTrade众汇实例这样使用

在后台经常有交易者咨询:“我可以用加权平均线或指数代替移动平均线吗?”理论上&#xff0c;任何平均值都适合绘制BB。在回答这个问题之前&#xff0c;为了稳妥起见&#xff0c;WeTrade众汇通过对各种均线对比分析&#xff0c;却得出这样结论:经典均线是构建参考点最简单、最准…

element-plus表格判断table中的数据是否换行展示,如果换行展示,替换为....

文章目录 需求分析 需求 element-plus表格判断table中的数据是否换行展示&#xff0c;如果换行展示&#xff0c;替换为… 分析 <style lang"less" scoped>::v-deep(.el-table .cell) {overflow: hidden; // 溢出隐藏text-overflow: ellipsis; // 溢出用省略号…

蓝桥杯(C++ 整数删除 优先队列 )

优先队列&#xff1a; 优先队列具有队列的所有特性&#xff0c;包括队列的基本操作&#xff0c;只是在这基础上添加了内部的一个排序&#xff0c;它本质是一个堆实现的。 1.头文件&定义 #include <queue> #include <functional> //greater<>// 定义 p…

如何使用@font-face

font-face css 提供的font-face可以让开发者自定义项目中的字体。字体可以从远程服务器获取&#xff0c;也可以从本地加载。 font-face {font-family: "Open Sans";src:url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2"),url(&qu…