SpringBoot3+Vue3+Mysql+Element Plus完成数据库存储blob类型图片,前端渲染后端传来的base64类型图片
前言
如果你的前后端分离项目采用SpringBoot3+Vue3+Element Plus,且在没有OSS(对象存储)的情况下,使用mysql读写图片(可能不限于图片,待测试)。
耗时三天,在踩了无数雷后,终于完成本功能。为你呈上。
本文完成功能:
- 前端采用Element发起上传图片请求,后端接收并将其存储到mysql。
- 后端相应图片base64数据,前端接收并渲染到页面。
1.前端上传到数据库
1.1前端上传图片
<el-form-item label="宠物照片" prop="pictureId">
<el-upload v-model="form.pictureId" :auto-upload="false" :action="''" :show-file-list="true" :on-change="handleAvatarChangeIcon"><el-button type="primary">选取文件</el-button>
</el-upload>
</el-form-item>
参数:
:auto-upload 是否自动上传
:action 自动上传的请求路径
:show-file-list 显示已上传的图片列表
:on-change 选中文件触发的change事件
自动上传与否都不影响,这里主要是判断一下图片的大小、后缀名。如下:
const handleAvatarChangeIcon = (file) => {// 限制文件后缀名const isJPG = file.raw.type === 'image/jpeg'const isPNG = file.raw.type === 'image/png'// 限制上传文件的大小const isLt5M = file.raw.size / 1024 / 1024 < 5if (!isPNG && !isJPG) {ElMessage.error('图片只能是 JPG/PNG 格式')return false} else if (!isLt5M) {ElMessage.error('图片应在5MB以内')return false} else {// 发起请求let param = new FormData();// 文件为form data格式param.append("file", file.raw);post('/api/file/upload', param, (res) => {ElMessage.success('上传成功');// 返回值为图片idform.pictureId = res})}
}
1.2后端接收并保存数据库
controller
@RestController
@RequestMapping("/api/file")
public class FileController {@Resourceprivate FileService fileService;@PostMapping("/upload")public RestBean<String> upload(@RequestParam MultipartFile file) {Integer res = fileService.upload(file);return RestBean.success(String.valueOf(res));}
}
serviceImpl
@Service
public class FileServiceImpl implements FileService {@Resourceprivate FileMapper fileMapper;/*** 文件上传到数据库*/@Overridepublic Integer upload(MultipartFile file) throws IOException {// 获取文件原始名String originalFilename = file.getOriginalFilename();// 获取文件后缀名String endName = "png";if (originalFilename != null) {endName = originalFilename.substring(originalFilename.lastIndexOf("."));}// 拼接文件名String filename = UUID.randomUUID() + endName;Integer pictureId;// 创建图片对象byte[] fileBytes = file.getBytes();Picture picture = new Picture();picture.setName(filename);picture.setPicData(fileBytes);// 上传数据库fileMapper.upload(picture);pictureId = picture.getId();// 返回图片idreturn pictureId;}
}
mapper.xml
<mapper namespace="com.ycb.mapper.FileMapper"><insert id="upload" useGeneratedKeys="true" keyProperty="id">insert into `pet-adoption`.picture(name, pic_data)value (#{name}, #{picData})</insert>
</mapper>
数据库设计

2.前端从数据库获取图片并渲染
2.1后端从数据库中获取
entity
public class PetAndBulVO {/*** 照片*/private byte[] picData;
}
controller
如果是一个图片数据直接封装到实体类,很多数据就封装成集合
@RequestMapping("/api/pet")
public class PetController {@Resourceprivate PetService petService;@GetMapping("/getAllPB")public RestBean<List<PetAndBulVO>> getAll() {List<PetAndBulVO> pets = petService.getAll();return RestBean.success(pets);}
}
serviceImpl
@Service
public class PetServiceImpl implements PetService {@Resourceprivate PetMapper petMapper;@Overridepublic List<PetAndBulVO> getAll() {return petMapper.getAll();}
}
mapper.xml
<mapper namespace="com.ycb.mapper.PetMapper"><!-- 一定要映射结果集 --><resultMap type="com.ycb.entity.vo.response.PetAndBulVO" id="petAndBulVO"><id column="pic_data" property="picData" javaType="byte[]" jdbcType="BLOB" typeHandler="org.apache.ibatis.type.BlobTypeHandler"/></resultMap><select id="getAll" resultMap="petAndBulVO">select *from `pet-adoption`.pet petjoin `pet-adoption`.picture p on p.id = pet.picture_id</select>
后端返回的图片数据如下:

2.2前端接收数据并渲染
后端传来的数据是 base64 形式的,需要解码
// 解码
const base64ToUrl = (base64) => {return 'data:image/png;base64,' + base64
}// 获取数据
get('/api/pet/getAllPB', (data) => {for (let i = 0; i < data.length; i++) {data[i].picData = base64ToUrl(data[i].picData)}pBList.value = data
}, (err) => {ElMessage.error(err)
})
解码后的图片数据如下:

渲染是大坑!一定要 v-bind: 绑定 src
// v-for循环获取picData, v-for="(pb) in pBList"
<el-image v-bind:src="pb.picData"/>
《林克可爱图》

写在最后
虽然可以实现仅用mysql就能完成图片读写,但其性能堪忧。
很难,但贵在坚持。
相关文章:
SpringBoot3+Vue3+Mysql+Element Plus完成数据库存储blob类型图片,前端渲染后端传来的base64类型图片
前言 如果你的前后端分离项目采用SpringBoot3Vue3Element Plus,且在没有OSS(对象存储)的情况下,使用mysql读写图片(可能不限于图片,待测试)。 耗时三天,在踩了无数雷后,…...
攻略 | 参与Moonbeam Ignite Ecosystem Tour
Moonbeam联合Moonwell和Beamswap一起举办社区链上活动,旨在让社区用户通过任务来探索Moonbeam、Moonwell、Beamswap平台。在了解如何使用的同时,参与任务挑战还有机会分得 1700 USDC 奖池 🎁 的奖励!我已经完成全部任务࿰…...
【python自动化】Playwright基础教程(七)Keyboard键盘
【python自动化】Playwright基础教程(七)Keyboard键盘 playwright模拟键盘操作 键盘事件提供了用于管理虚拟键盘的API,高级API是keyboard.type(),它使用的是原始字符再页面上生成对应的keydown 、 keypress / input 和 keyup 事件。 模拟真实键盘操作进行…...
Java读取文件内容写入新文件
要实现读写文件这个过程我们需要导入以下的包 import java.io.BufferedReader; import java.io.BufferedWriter;BufferedReader 用于逐行读取源文件的内容,BufferedWriter 用于逐行写入目标文件。 下面以示例了解如何操作: import java.io.BufferedRe…...
学习samba
文章目录 一、samba介绍二、samba的主要进程三、配置文件四、例子 一、samba介绍 1、SMB(Server Message Block)协议实现文件共享,也称为CIFS(Common Internet File System)。 2、是Windows和类Unix系统之间共享文件的…...
【Ansible】Ansible的Ad-hoc命令执行流程
Ansible的Ad-hoc命令执行流程 用了这么久的Ansible,今天想着研究下Ad-hoc命令的执行流程,从最简单的ping开始吧。 测试命令如下: ansible 172.18.2.31 -m ping先看看回显的结果 [rootbigdata-m-002 etc]# ansible 172.18.2.31 -m ping 17…...
Postgresql 常用整理
文章目录 1. 查询1.1数据库表1.1.1 获取指定数据库表1.1.2 获取指定数据库表所有列名 1.2 别名1.2.1 子表指定别名1.2.2 查询结果指定别名 1.3 临时表1.3.1 定义临时表1.3.2 使用临时表 1.4 子表1.5 分组1.5.1 group by1.5.2 partition by 1.6 分组后合并指定列字段:…...
如何在Jupyter Lab中安装不同的Kernel
❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…...
Java钩子函数的使用
目录 1. Java中常见的钩子函数 2. 使用钩子函数实现程序的清理工作 3. 使用钩子函数处理线程中的未捕获异常 4. 使用钩子函数实现窗口关闭时的操作 在Java编程中,钩子函数(Hook Function)是一种能够在特定事件发生时执行的代码块。钩子函…...
C++跨DLL内存所有权问题探幽(一)DLL提供的全局单例模式
最近在开发的时候,特别是遇到关于跨DLL申请对象、指针、内存等问题的时候遇到了这么一个问题。 问题 跨DLL能不能调用到DLL中提供的单例? 问题比较简单,就是我现在有一个进程A,有DLL B DLL C,这两个DLL都依赖DLL D的…...
短时间不点击云服务器,自动化断开连接,怎么设置长时间
在 Linux 系统中,如果你希望在一段时间内没有操作后保持远程连接不断开,可以通过修改 SSH 服务器的配置来实现。具体的步骤如下: 打开 SSH 服务器的配置文件: sudo vi /etc/ssh/sshd_config 找到以下两个参数并进行修改ÿ…...
typhonjs-escomplex 代码可读性 可维护度探索
目前市面上的前端代码质量评分中的代码可维护度是大都是基于 typhonjs-escomplex 这个库扫描而来,但是这个库的官方文档并没有介绍相关指标数据的计算规则,不知道规则如何提升指标数据呢?所以本文对 typhonjs-escomplex 源码进行探索…...
支持向量机基本原理,Libsvm工具箱详细介绍,基于支持向量机SVM的人脸朝向识别
目录 支持向量机SVM的详细原理 SVM的定义 SVM理论 Libsvm工具箱详解 简介 参数说明 易错及常见问题 完整代码和数据下载链接: 基于支持向量机SVM人脸朝向识别(代码完整,数据齐全)资源-CSDN文库 https://download.csdn.net/download/abc991835105/88527821 SVM应用实例, 基…...
密码破解工具的编写
预计更新 网络扫描工具的编写漏洞扫描工具的编写Web渗透测试工具的编写密码破解工具的编写漏洞利用工具的编写拒绝服务攻击工具的编写密码保护工具的编写情报收集工具的编写 密码破解工具是一种常见的安全工具,它可以通过不断尝试不同的密码组合来破解加密的数据或…...
BES2700H开发不完全手册
BES2700H开发不完全手册 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,群赠送语音信号处理降噪算法,ANC AEC ENC EQ BF BES蓝牙耳机音频资料 1 成功编译 2 代码 3 开放文档...
OpenGL的学习之路-3
前面1、2介绍的都是glut编程 下面就进行opengl正是部分啦。 1.绘制点 #include <iostream> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h>void myMainWinDraw();int main(int argc,char** argv) {glutInit(&argc,argv);glutIni…...
Vue 小黑记事本组件版
渲染功能: 1.提供数据: 提供在公共的父组件 App.vue 2.通过父传子,将数据传递给TodoMain 3.利用 v-for渲染 添加功能: 1.收集表单数据 v-model 2.监听事件(回车点击都要添加) 3.子传父,讲…...
javascript如何清空数组?
可以使用以下方法清空JavaScript数组: 直接赋值为空数组 arr []; let arr [1, 2, 3, 4]; arr []; // 现在arr是空数组使用 splice() 方法删除所有元素 let arr [1, 2, 3, 4]; arr.splice(0, arr.length); // 现在arr是空数组使用 length 属性将数组截断 let ar…...
MySQL MHA高可用切换
MySQL MHA 1.什么是 MHA MHA(MasterHigh Availability)是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。 MHA 的出现就是解决MySQL 单点的问题。 MySQL故障切换过程中,MHA能做到0-30秒内自动完成故障切换操作。 MHA能在…...
【Python】【应用】Python应用之一行命令搭建http、ftp服务器
🐚作者简介:花神庙码农(专注于Linux、WLAN、TCP/IP、Python等技术方向)🐳博客主页:花神庙码农 ,地址:https://blog.csdn.net/qxhgd🌐系列专栏:Python应用&…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
JS红宝书笔记 - 3.3 变量
要定义变量,可以使用var操作符,后跟变量名 ES实现变量初始化,因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符,可以创建一个全局变量 如果需要定义…...
