SpringBoot+Vue实现图片上传
以SpringBoot作为的后端服务,搭配Vue实现图片上传功能。支持图片实时预览、一键删除操作,并内置多重安全校验机制:严格限制上传图片类型(如JPG/PNG/GIF等)、控制单次上传数量阈值、设置文件大小上限,确保数据传输的安全性与流畅性。
一、效果展示
二、实现代码
1、技术介绍
- 后端框架:SpringBoot
- 前端框架:Vue3+JS+Eelement Plus
2、后端实现代码
- FileUploadController.java:图片保存
package com.general.utils;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.io.File;
import java.io.IOException;/*** 图片上传*/
@RestController
public class FileUploadController {// 图片上传路径@Value("${img.path}")private String basePath;@PostMapping("/upload")public ResponseEntity uploadImage(@RequestParam("file") MultipartFile file) {// file是个临时文件,需要转存到指定路径才能永久保存// 截取原始文件名的后缀String originalFilename = file.getOriginalFilename();String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));// 使用uuid重新生成文件名String fileName = SysUtil.getUuid() + suffix;// 创建一个目录对象File dir = new File(basePath);if (!dir.exists()) {// 目录若不存在,则创建dir.mkdir();}try {// 将文件转存到指定位置file.transferTo(new File(basePath + fileName));} catch (IOException e) {e.printStackTrace();}return ResponseEntity.ok("http://localhost:9491/" + fileName);}/*** @return* @Bean注入 实现图片的访问预览*/@Beanpublic WebMvcConfigurer corsConfigurer() {return new WebMvcConfigurer() {public void addResourceHandlers(ResourceHandlerRegistry registry) {//设置请求路径,映射到指定路径registry.addResourceHandler("/**").addResourceLocations("file:" + basePath);}};}
}
3、前端实现代码
- imageUpload.vue:图片上传组件
<template><div class="image-upload"><el-upload action="http://localhost:9491/upload" :file-list="fileList" :on-success="handleSuccess" :on-preview="handlePreview" :on-remove="handleRemove" :on-exceed="handleExceed" :before-upload="beforeUpload" :show-file-list="true" :multiple="multiple" :limit="limit" :accept="acceptType" list-type="picture-card"><el-icon><Plus /></el-icon></el-upload><!-- 图片预览对话框 --><el-dialog v-model="previewVisible" append-to-body><img :src="previewImage" alt="预览" style="width: 100%"></el-dialog></div>
</template>
<script>export default {name: 'ImageUpload',props: {modelValue: {type: Array,default: () => []},multiple: {type: Boolean,default: false},limit: {type: Number,default: 1},acceptType: {type: String,default: 'image/jpeg,image/png,image/gif'},maxSize: {type: Number,default: 5 // MB},},emits: ['update:modelValue'],data() {return {fileList: [],previewImage: '',previewVisible: false,};},watch: {modelValue: {immediate: true,handler(val) {// 将逗号分隔的字符串转换为数组(处理空值和空格)const fileArray = typeof val === 'string' ? val.split(',').map(item => item.trim()) // 去除每个路径两端的空格.filter(item => item) // 过滤空字符串(如连续逗号产生的空项): Array.isArray(val) ? val : []; // 如果已经是数组则直接使用// 生成文件列表this.fileList = fileArray.map(item => ({url: item,name: item.substring(item.lastIndexOf('/') + 1), // 提取文件名status: 'success'}));}}},methods: {// 上传前校验beforeUpload(file) {const isImage = this.acceptType.split(',').includes(file.type);const isLtMaxSize = file.size / 1024 / 1024 < this.maxSize;if (!isImage) {this.$message.error('上传文件格式错误!');return false;}if (!isLtMaxSize) {this.$message.error(`上传文件大小不能超过 ${this.maxSize}MB!`);return false;}return true;},// 上传成功处理handleSuccess(response, file, fileList) {const url = fileList.map(item => item.response);if (this.modelValue.length > 0) {const urls = this.modelValue + ',' + url.join(",");this.$emit('update:modelValue', urls)} else {const urls = url.join();this.$emit('update:modelValue', urls)}},// 删除文件处理handleRemove(file, fileList) {const urls = fileList.map(item => item.url);this.$emit('update:modelValue', urls.join())},// 预览图片handlePreview(file) {this.previewImage = file.url;this.previewVisible = true;},handleExceed() {this.$message.warning('最多只能上传' + this.limit + '个文件');},}};
</script>
<style scoped>.image-upload {display: inline-block;}
</style>
- sysUser.vue:组件的使用
<imageUpload v-model="dataForm.img" :limit="1"></imageUpload>