SpringBoot3+Vue3+Mysql+Element Plus completes the database storage of blob type images, and the front end renders the base64 type images transmitted from the back end.

Foreword

If your front-end and back-end separation project uses SpringBoot3 + Vue3 + Element Plus, and without OSS (object storage), use mysql to read and write images (may not be limited to images, to be tested).

It took three days and after stepping on countless minefields, this function was finally completed. Presented to you.

Complete functions of this article:

  1. The front end uses Element to initiate an image upload request, and the back end receives and stores it in mysql.
  2. The back-end corresponding image base64 data is received by the front-end and rendered to the page.

1. Upload the front end to the database

1.1 Front-end upload pictures

<el-form-item label="Pet Photo" prop="pictureId">
<el-upload v-model="form.pictureId" :auto-upload="false" :action="''"
           :show-file-list="true" :on-change="handleAvatarChangeIcon">
  <el-button type="primary">Select file</el-button>
</el-upload>
</el-form-item>

parameter:

:auto-upload whether to automatically upload

:action request path for automatic upload

:show-file-list displays the uploaded image list

:on-change Change event triggered by selected file

It doesn’t matter whether it is automatically uploaded or not. The main thing here is to determine the size and suffix of the image. as follows:

const handleAvatarChangeIcon = (file) => {<!-- -->
  //Limit file suffix name
  const isJPG = file.raw.type === 'image/jpeg'
  const isPNG = file.raw.type === 'image/png'
  // Limit the size of uploaded files
  const isLt5M = file.raw.size / 1024 / 1024 < 5
  if (!isPNG & amp; & amp; !isJPG) {<!-- -->
    ElMessage.error('Pictures can only be in JPG/PNG format')
    return false
  } else if (!isLt5M) {<!-- -->
    ElMessage.error('Picture should be within 5MB')
    return false
  } else {<!-- -->
    // Initiate request
    let param = new FormData();
    //The file is in form data format
    param.append("file", file.raw);
    post('/api/file/upload', param, (res) => {<!-- -->
      ElMessage.success('Upload successful');
      //The return value is the image id
      form.pictureId = res
    })
  }
}

1.2 backend receives and saves the database

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

@Service
public class FileServiceImpl implements FileService {<!-- -->
    @Resource
    private FileMapper fileMapper;

    /**
     * Upload files to database
     */
    @Override
    public Integer upload(MultipartFile file) throws IOException {<!-- -->
        // Get the original name of the file
        String originalFilename = file.getOriginalFilename();
        // Get the file extension name
        String endName = "png";
        if (originalFilename != null) {<!-- -->
            endName = originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        // Splice file names
        String filename = UUID.randomUUID() + endName;
        Integer pictureId;
        //Create image object
        byte[] fileBytes = file.getBytes();
        Picture picture = new Picture();
        picture.setName(filename);
        picture.setPicData(fileBytes);
        //Upload database
        fileMapper.upload(picture);
        pictureId = picture.getId();
        // Return image 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>

Database Design

2. The front end obtains images from the database and renders them

2.1 backend gets from database

entity

public class PetAndBulVO {<!-- -->
    /**
     * photo
     */
    private byte[] picData;
}

controller

If an image data is directly encapsulated into an entity class, a lot of data is encapsulated into a collection.

@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

@Service
public class PetServiceImpl implements PetService {<!-- -->
    @Resource
    private PetMapper petMapper;

    @Override
    public List<PetAndBulVO> getAll() {<!-- -->
        return petMapper.getAll();
    }
}

mapper.xml

<mapper namespace="com.ycb.mapper.PetMapper">
    <!-- The result set must be mapped -->
    <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>

The image data returned by the backend is as follows:

2.2 Front-end receives data and renders

The data transmitted from the backend is in base64 format and needs to be decoded.

// decoding
const base64ToUrl = (base64) => {
    return 'data:image/png;base64,' + base64
}

// retrieve data
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)
})

The decoded image data is as follows:

Rendering is a big pitfall! Be sure to v-bind: bind src

// v-for loop to obtain picData, v-for="(pb) in pBList"
<el-image v-bind:src="pb.picData"/>

“Link Cute Picture”

Write at the end

Although it is possible to read and write images using only mysql, its performance is worrying.

It’s difficult, but persistence is important.