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应用&…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...
恶补电源:1.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...
C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...
对象回调初步研究
_OBJECT_TYPE结构分析 在介绍什么是对象回调前,首先要熟悉下结构 以我们上篇线程回调介绍过的导出的PsProcessType 结构为例,用_OBJECT_TYPE这个结构来解析它,0x80处就是今天要介绍的回调链表,但是先不着急,先把目光…...
