使用springboot与vue开发头像功能

发布于:2025-03-21 ⋅ 阅读:(29) ⋅ 点赞:(0)

1.建立数据库表

CREATE TABLE `file` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `size` bigint DEFAULT NULL,
  `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `md5` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `is_delete` tinyint(1) DEFAULT '0',
  `is_enable` tinyint(1) DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=61 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

2.后端接口实现

实体类服务类

直接用mybatisplus代码生成,注意实体类名字是Files避免与java中的File重复

控制器

md5保证文件的唯一性,节省磁盘空间

@PostMapping("/upload")
        public String upload(@RequestParam MultipartFile file) throws IOException {
            String originalFilename = file.getOriginalFilename();
            String type = FileUtil.extName(originalFilename);
            long size = file.getSize();
            File uploadParentFile = new File(fileUploadPath);
            // 判断目录是否存在
            if (!uploadParentFile.exists()) {
                uploadParentFile.mkdirs(); // 使用mkdirs()确保所有父目录都被创建
            }
            // 定义md5
            String md5 = SecureUtil.md5(file.getInputStream());
            Files queryFiles = queryByMd5(md5);
            String url;
            if (queryFiles == null) {
                // 定义唯一的文件标识码
                String uuid = IdUtil.fastSimpleUUID();
                String UUID = uuid + StrUtil.DOT + type;
                File uploadFile = new File(fileUploadPath + UUID); // 路径名字
                file.transferTo(uploadFile); // 文件写入指定对象
                // 存储磁盘
                url = "http://" + serverIp + ":9090/file/" + UUID;
                // 存储数据库
                Files saveFile = new Files();
                saveFile.setType(type);
                saveFile.setSize(size / 1024);
                saveFile.setName(originalFilename);
                saveFile.setUrl(url);
                saveFile.setMd5(md5);
                fileMapper.insert(saveFile);
            } else {
                url = queryFiles.getUrl();
            }
            return url;
        }
/**
         * 根据文件UUID下载文件
         * 
         * @param fileUUID 文件的唯一标识符,用于定位存储的文件
         * @param response HTTP响应对象,用于输出文件流和设置响应头
         * @throws IOException 如果文件读取或输出流操作失败
         */
        @GetMapping("/{fileUUID}")
        public void download(@PathVariable String fileUUID, HttpServletResponse response) throws IOException {
            // 根据文件UUID创建File对象,用于后续的文件读取操作
            File downloadFile = new File(fileUploadPath + fileUUID);
            // 获取响应的输出流,用于向客户端发送文件数据
            ServletOutputStream outputStream = response.getOutputStream();
            // 设置响应头,指示浏览器以附件形式下载文件,并指定文件名
            response.addHeader("Content-Disposition","attachment;filenmae="+ URLEncoder.encode(fileUUID,"UTF-8"));
            // 设置响应的内容类型,表示以二进制流的形式传输文件
            response.setContentType("application/octet-stram");
            // 读取文件字节流
            outputStream.write(FileUtil.readBytes(downloadFile));
            // 刷新输出流,确保所有数据都被写入响应
            outputStream.flush();
            // 关闭输出流,释放资源
            outputStream.close();
        }

前端

    //页面结构
    <el-upload
                class="avatar-uploader"
                :action="'http://'+'localhost' +':9090/file/upload'"
                :show-file-list="true"
                :on-success="handleAvatarSuccess"
                :before-upload="beforeAvatarUpload"
              >
                <img v-if="user.avatar" :src="user.avatar" class="avatar" style="">
                <i v-else class="el-icon-plus avatar-uploader-icon"></i>
    </el-upload>
    submitUser(){
          console.log(this.user)
          this.request.post("/user/save", this.user).then(res => {
            if (res.code==200) {
              this.$message.success("修改成功")
              localStorage.setItem("userInfo", JSON.stringify(this.user))
              this.$emit("refreshUser")//让header的头像信息更新
            } else {
              this.$message.error(res.msg)
            }
          })
        },

        handleAvatarSuccess(res){
            this.$message.success("上传成功")
            console.log(res)
            this.user.avatar = res
        },
        beforeAvatarUpload(file) {
            const isJPG = file.type === 'image/jpeg';
            const isLt2M = file.size / 1024 / 1024 < 1;
    
            if (!isJPG) {
              this.$message.error('上传头像图片只能是 JPG 格式!');
            }
            if (!isLt2M) {
              this.$message.error('上传头像图片大小不能超过 1MB!');
            }
            return isJPG && isLt2M;
        }
    .avatar-uploader{
      text-align:center;
      padding-bottom: 10px;
    }
    .avatar-uploader .el-upload {
        border: 1px dashed #d9d9d9;
        border-radius: 6px;
        cursor: pointer;
        position: relative;
        overflow: hidden;
      }
      .avatar-uploader .el-upload:hover {
        border-color: #409EFF;
      }
      .avatar-uploader-icon {
        font-size: 28px;
        color: #8c939d;
        width: 138px;
        height: 138px;
        line-height: 138px;
        text-align: center;
      }
      .avatar {
        width: 138px;
        height: 138px;
        display: block;
      }

4.效果

在这里插入图片描述