图文并茂:解析Spring Boot Controller返回图片的三种方式

图文并茂:解析Spring Boot Controller返回图片的三种方式
- 前言
- 使用Base64编码返回图片
- 使用byte数组返回图片
- 使用Resource对象返回图片
- 图片格式转换与性能对比
前言
在互联网的世界里,图片无处不在,它们是信息传递的重要媒介,也是视觉盛宴的一部分。而在Spring Boot项目中,如何优雅地处理和返回图片数据,则成为了开发者们不得不面对的问题。今天,就让我们一起来探索Spring Boot Controller的神奇转换,看看如何在代码的世界里展现出美丽的图画吧!
使用Base64编码返回图片
Base64 编码是一种将二进制数据转换为 ASCII 字符串的编码方式。它的原理是将每 3 个字节(24 位)的二进制数据编码成 4 个字符的 ASCII 字符串,因此 Base64 编码后的字符串长度会比原始数据增加约 1/3。Base64 编码的优势在于可以在文本协议中(如 JSON、XML)安全地传输二进制数据,同时不会丢失数据内容。
优点:
- 可读性好: Base64 编码的结果是 ASCII 字符串,可以在文本协议中直接显示,方便阅读和传输。
- 二进制数据安全传输: 在一些不支持二进制数据传输的环境中(如 HTTP 请求、XML 数据格式),使用 Base64 编码可以将二进制数据安全地转换成文本数据传输。
- 字符集兼容性: Base64 编码只使用了字母、数字和一些特殊字符,因此在各种字符集下都可以正确传输。
缺点:
- 数据体积膨胀: Base64 编码会导致数据体积膨胀约 1/3,这可能会增加传输数据量和网络带宽的消耗。
- 性能影响: 对于大型二进制数据,Base64 编码和解码可能会消耗一定的 CPU 资源和时间。
在 Spring Boot Controller 中将图片转换为 Base64 编码的字符串并返回的示例代码如下:
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.io.File;
import java.io.IOException;
import java.nio.file.Files;@RestController
public class ImageController {@GetMapping("/image")public String getImageAsBase64() throws IOException {// 读取图片文件File file = new File("path/to/your/image.jpg");byte[] imageBytes = Files.readAllBytes(file.toPath());// 将图片字节数组进行 Base64 编码String base64EncodedImage = Base64Utils.encodeToString(imageBytes);// 返回 Base64 编码后的图片字符串return base64EncodedImage;}
}
在这个示例中,我们首先读取了图片文件的字节数组,然后使用 Spring 的 Base64Utils
类将字节数组进行 Base64 编码,并将结果作为字符串返回给客户端。
使用byte数组返回图片
使用 byte 数组返回图片通常适用于需要在客户端直接显示图片的场景,而不是将图片作为文件下载。这种方式可以在减少网络传输数据的同时,直接将图片数据嵌入到 HTTP 响应中,从而加快客户端的加载速度和提升用户体验。适用场景包括网页中的图片展示、移动应用中的图片加载等。
在 Spring Boot Controller 中将图片转换为 byte 数组并返回的示例代码如下:
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;@RestController
public class ImageController {@GetMapping("/image")public ResponseEntity<byte[]> getImageAsByteArray() throws IOException {// 读取图片文件File file = new File("path/to/your/image.jpg");byte[] imageBytes = Files.readAllBytes(file.toPath());// 构建 HTTP 响应头HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.IMAGE_JPEG);headers.setContentLength(imageBytes.length);// 返回包含图片字节数组的 ResponseEntityreturn new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);}
}
在这个示例中,我们使用了 ResponseEntity 来构建 HTTP 响应,并将图片的 byte 数组作为响应体返回。我们还设置了响应头中的 Content-Type 为 image/jpeg,表明返回的内容是 JPEG 格式的图片。
使用Resource对象返回图片
使用 Resource
对象返回图片在 Spring Boot 应用中的优势之一是它可以轻松地处理图片文件位于不同位置的情况,包括位于文件系统、类路径、网络等不同位置。这样可以使代码更具灵活性和可移植性,同时使得图片的加载和返回更加简洁。
适用场景包括需要对图片的位置进行动态配置、需要从远程服务器或第三方服务加载图片、需要在分布式环境下加载图片等情况。
在 Spring Boot Controller 中使用 Resource
对象加载并返回图片的示例代码如下:
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;import java.io.IOException;@RestController
public class ImageController {@GetMapping("/image")public ResponseEntity<Resource> getImage() throws IOException {// 加载图片资源Resource resource = loadResource("path/to/your/image.jpg");// 构建响应return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(resource);}private Resource loadResource(String imagePath) {// 实现加载图片资源的逻辑,这里可以是文件系统、类路径、网络等不同位置// 这里的示例是加载文件系统中的图片return new FileSystemResource(imagePath);}
}
在这个示例中,loadResource
方法用于加载图片资源,你可以根据实际情况实现具体的加载逻辑。在 getImage
方法中,我们将加载的图片资源封装成 Resource
对象,并将其包装在 ResponseEntity
中返回给客户端。
图片格式转换与性能对比
在分析三种方式的性能特点和适用场景之前,让我们先来看一下它们各自的优劣和适用情况:
-
Base64 编码返回图片:
- 优点:可以直接将图片编码为字符串嵌入到文本协议中,无需额外的 HTTP 请求。
- 缺点:Base64 编码会导致数据体积膨胀,增加网络传输负载;在大量图片或大图的情况下,会增加服务器和客户端的 CPU 开销。
- 适用场景:适用于图片大小较小,或者只有少量图片需要显示的场景,且对网络传输负载和 CPU 开销要求不高的情况。
-
使用 byte 数组返回图片:
- 优点:直接返回图片的字节数组,避免了 Base64 编码带来的数据体积膨胀。
- 缺点:仍然需要通过 HTTP 请求来获取图片数据,可能增加网络传输负载。
- 适用场景:适用于需要动态生成图片或者从外部系统获取图片的情况,且对网络传输负载和服务器 CPU 开销要求不高的情况。
-
使用 Resource 对象返回图片:
- 优点:可以灵活处理图片的位置,支持从文件系统、类路径、网络等不同位置加载图片,具有较高的灵活性和可移植性。
- 缺点:需要通过 HTTP 请求来获取图片数据,可能增加网络传输负载。
- 适用场景:适用于需要动态加载图片、图片位置不固定或需要从远程服务获取图片的情况。
性能对比和调优建议:
- Base64 编码和 byte 数组返回图片的方式可以减少 HTTP 请求的数量,但会增加单次请求的数据量,因此在需要频繁请求小量图片的场景中适用。如果图片较大或者数量较多,建议使用 Resource 对象返回图片,通过懒加载的方式减少一次性加载大量图片数据带来的性能压力。
- 在高并发情况下,尽量减少服务器端的 CPU 开销,可以通过使用 CDN 加速、图片格式优化(如 JPEG 图片压缩)等方式来提升性能。
相关文章:

图文并茂:解析Spring Boot Controller返回图片的三种方式
欢迎来到我的博客,代码的世界里,每一行都是一个故事 图文并茂:解析Spring Boot Controller返回图片的三种方式 前言使用Base64编码返回图片使用byte数组返回图片使用Resource对象返回图片图片格式转换与性能对比 前言 在互联网的世界里&…...
问题处理记录 | 表输出报错 Packet for query is too large (5,214,153 > 4,194,304).
这个错误是由于MySQL服务器接收到的查询数据包太大而引起的。具体来说,错误消息中提到的数据包大小为5,214,153字节,而MySQL服务器默认只接受最大为4,194,304字节的数据包。 要解决这个问题,你可以尝试通过修改MySQL服务器的配置来增大max_a…...

数据结构_栈和队列(Stack Queue)
✨✨所属专栏:数据结构✨✨ ✨✨作者主页:嶔某✨✨ 栈: 代码:function/数据结构_栈/stack.c 钦某/c-language-learning - 码云 - 开源中国 (gitee.com)https://gitee.com/wang-qin928/c-language-learning/blob/master/function/…...

基于docker 的elasticsearch冷热分离及生命周期管理
文章目录 冷热集群架构的应用场景冷热集群架构的优势冷热集群架构实战搭建集群 索引生命周期管理认识索引生命周期索引生命周期管理的历史演变索引生命周期管理的基础知识Rollover:滚动索引 冷热集群架构的应用场景 某客户的线上业务场景如下:系统每天增…...

pikachu靶场(xss通关教程)
(注:若复制注入代码攻击无效,请手动输入注入语句,在英文输入法下) 反射型xss(get型) 1.打开网站 发现有个框,然后我们在框中输入一个“1”进行测试, 可以看到提交的数据在url处有显示…...

实验0.0 Visual Studio 2022安装指南
Visual Studio 2022 是一个功能强大的开发工具,对于计算机专业的学生来说,它不仅可以帮助你完成学业项目,还能为你将来的职业生涯打下坚实的基础。通过学习和使用 Visual Studio,你将能够更高效地开发软件,并在编程领域…...
数据结构之----线性表
线性表分为 顺序存储结构 和 链式存储结构 线性表的顺序存储结构: 线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。 1,顺序表的结构: #define MAXSIZE 20 typedef int El…...
thinkphp5.1 模型auto
在ThinkPHP5.1中,模型的自动完成功能可以通过在模型类中定义auto属性来实现。这个属性是一个数组,包含了需要自动填充的字段和对应的处理规则。 以下是一个简单的例子,展示了如何在ThinkPHP5.1的模型中使用自动完成功能: <?…...

企业微信创建应用(一)
登录到企业微信后台管理(https://work.weixin.qq.com/)进入自建应用(应用管理-应用-创建应用) 3.查看参数AgentId和 Secret 4.企业微信查看效果...

Cosmo Bunny Girl
可爱的宇宙兔女郎的3D模型。用额外的骨骼装配到Humanoid上,Apple混合了形状。完全模块化,包括不带衣服的身体。 技术细节 内置,包括URP和HDRP PDF。还包括关于如何启用URP和HDRP的说明。 LOD 0:面:40076,tris 76694,verts 44783 装配了Humanoid。添加到Humanoid中的其他…...

初始化linux数据盘(3TB)分区-格式化-挂载目录
场景说明:某云给我们服务器加载了一块3TB的硬盘扩容(没有直接扩,原因是原来的盘做的是mbr(什么年代了,谁干的)的分区,最大识别2TB) 确认磁盘 输入命令lsblk 查看数据盘信息 &#…...
NFS网络文件系统的应用
1.配置2台服务器要求如下: a)服务器1: 主机名:user-server.timinglee.org ip地址: 172.25.254.100 [rootserver100 桌面]# hostnamectl hostname user-server.timinglee.org [rootserver100 桌面]# ifconfig eth0: fl…...

AttributeError: module ‘PIL.Image‘ has no attribute ‘ANTIALIAS‘
问题描述 修改图片大小的时候,代码报错:AttributeError: module PIL.Image has no attribute ANTIALIAS 解决方案 在pillow的10.0.0版本中,ANTIALIAS方法被删除了。 方法1:修改版本(不推荐) pip instal…...

进程的共享主存通信实验
进程的共享主存通信 【预备知识】 共享存储区为进程提供了直接通过主存进行通信的有效手段,不像消息缓冲机制那样需要系统提供缓冲,也不像pipe机制那样需要事先建立一个特殊文件,而是由通信双方直接访问某些共享虚拟储存空间。在Linux中&…...

深度缓冲技术在AI去衣中的神奇作用
引言: 随着人工智能技术的飞速发展,其在图形处理和视觉领域的应用日益增多。AI去衣技术便是其中一个颇具争议但又技术上引人入胜的话题。今天,我们将深入探讨一项关键技术——深度缓冲(Depth Buffering),它…...

能效?性能?一个关于Windows下使用openssl speed进行速度测试的诡异问题
问题描述 最近的某个软件用到了openssl,所以就想着测试一下速度。我的电脑是惠普的,CPU是AMD Ryzen 7 PRO 6850HS,系统是Win11。我使用openssl自带的speed测试加密/解密的速度,命令大致如下: openssl speed -evp aes…...
block性能考虑和线程安全
性能考虑 频繁地创建和销毁大量的 block 可能会对性能造成影响,特别是当这些 block 被拷贝到堆上时。同时,block 捕获大量数据时也会增加内存使用。 在讨论性能考虑时,主要关注的是 block 的创建、拷贝到堆上以及捕获变量的成本。以下是针对…...

没有公网ip,如何实现外网访问内网?
目前拨号上网是最广泛的上网方式,这种方式优点是价格便宜,缺点是没有固定公网ip,每次重新您拨号ip地址都会变。如果有一台服务器,需要实现外网访问,在没有固定公网ip的环境下,该如何实现呢?使用…...
Python中如何将小数转化为百分数进行输出
小数转化为百分数 Python中如何将小数转化为百分数进行输出基本概念使用字符串格式化1. 使用字符串格式化操作符 %2. 使用str.format()方法3. 使用f-string(格式化字符串字面量) **重点内容**:**无论是通过使用%格式化操作符、str.format()方…...

加入全球少儿编程运动:Scratch让每个孩子都能成为创造者(Scratch最新版客户端和初/中/高级学习资料整理分享)
文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 安装与使用📝 社区与资源 🎈 获取方式 🎈⚓️ 相关链接 ⚓️ 📖 介绍 📖 你知道…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...

MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...

Xcode 16 集成 cocoapods 报错
基于 Xcode 16 新建工程项目,集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...