当前位置: 首页 > article >正文

使用springboot与vue开发头像功能

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.效果

在这里插入图片描述


http://www.kler.cn/a/592602.html

相关文章:

  • 优化器/模型参数/超参数
  • 【Java篇】一气化三清:类的实例化与封装的智慧之道
  • 【深度学习】走向VQ-VAE模型
  • 【Python】使用ImageEnhance提升图片画质
  • windows 10 系统配置Node
  • 使用htool工具导出和导入Excel表
  • AI 原生 IDE Trae 深度体验:SSHremote 功能如何重新定义远程开发与云原生部署
  • 基于Python+Django的旅游管理系统
  • 13-动态规划-最长公共子序列
  • CVPR2025 | TAPT:用于视觉语言模型鲁棒推理的测试时对抗提示调整
  • C++学习笔记(二十三)——STL标准库
  • 握手问题 第十五届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组
  • 通过C#脚本更改材质球的参数
  • Flutter TextField 从入门到精通:掌握输入框的完整指南
  • 【链表】一文搞定链表算法:从基础到实战
  • 在线教育网站项目第四步:deepseek骗我, WSL2不能创建两个独立的Ubuntu,但我们能实现实例互访及外部访问
  • 记:app启动更换系统语言,app会重走生命周期
  • 【vue3+vant】移动端 - 部门树下拉选择组件 DeptTreeSelect 开发
  • rip 协议详细介绍
  • vue 中常用操作数组的方法