您现在的位置是:首页 > 短信大全

SpringBoot3+Vue3+Mysql+Element Plus完成数据库存储blob类型图片,前端渲染后端传来的base64类型图片

作者:欧阳逸时间:2024-03-28 13:25:41分类:短信大全

简介  文章浏览阅读949次,点赞2次,收藏3次。前后端分离项目采用SpringBoot3+Vue3+Element Plus,且在没有OSS(对象存储)的情况下,使用mysql读写图片(可能不限于图片,待测试)。前端采用Element发起上传图片请求,后端接收并将其

点击全文阅读

前言

如果你的前后端分离项目采用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 < 5  if (!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('上传成功');      // 返回值为图片id      form.pictureId = res    })  }}

1.2后端接收并保存数据库

controller

@RestController@RequestMapping("/api/file")public class FileController {    @Resource    private FileService fileService;    @PostMapping("/upload")    public RestBean<String> upload(@RequestParam MultipartFile file) {        Integer res = fileService.upload(file);        return RestBean.success(String.valueOf(res));    }}

serviceImpl

@Servicepublic class FileServiceImpl implements FileService {    @Resource    private FileMapper fileMapper;    /**     * 文件上传到数据库     */    @Override    public 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();        // 返回图片id        return 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 {    @Resource    private PetService petService;    @GetMapping("/getAllPB")    public RestBean<List<PetAndBulVO>> getAll() {        List<PetAndBulVO> pets = petService.getAll();        return RestBean.success(pets);    }}

serviceImpl

@Servicepublic class PetServiceImpl implements PetService {    @Resource    private PetMapper petMapper;    @Override    public 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 pet                 join `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就能完成图片读写,但其性能堪忧。

很难,但贵在坚持。

点击全文阅读

郑重声明:

本站所有活动均为互联网所得,如有侵权请联系本站删除处理

我来说两句