vue+Springboot实现头像预览及上传


请注意,项目使用vue3 + Element-Plus 2.3.7 + springboot 2.7.8!

思路说明

element-plus提供了el-upload组件实现头像上传,具体的属性说明请参考官方文档
组件拿到用户上传的图片之后,首先需要展示,用户确认后再传输给后端,后端接收图片资源后进行保存,并将保存状态返回给前端。

代码实现

前端代码

  • 前端代码-template
<el-dialog class="avatarDialog" :showClose="false" center v-model="avatarDialogVisible" title="更新头像">
      <el-upload ref="upload" class="avatar-uploader" :before-upload="beforeAvatarUpload" action="#"
               :http-request="uploadFile" :auto-upload="false" multiple list-type="picture-card" :file-list="fileList"
               :on-change="fileChange">
           <el-icon>
               <Plus />
           </el-icon>
           <template #file="{ file }">
               <img :src="file.url" alt="" />
           </template>
       </el-upload>
       <template #footer>
           <span class="dialog-footer">
               <el-button type="primary" @click="handleUpdateAvatar">
                   确认更新
               </el-button>
               <el-button @click="cancel">取消</el-button>
           </span>
       </template>
 </el-dialog>

这里对用到的属性进行简单解释:

1、before-upload:是el-upload组件提供的钩子函数,在图片上传之前执行,一般用于检查图片的格式和大小是否满足条件
2、action属性:图片上传到后端的路径,我这里不使用该属性,用“#”占位(你可以用其它字符串),后面使用自定义的上传方法。这里有个小坑,使用该属性会出现跨域问题
3、http-request:自定义的上传方法,会覆盖默认的xhr上传行为,如果需要使用它,你得关闭自动上传,即auto-upload=“false”
4、list-type:选中文件后以什么样的形式展示,可选值有:text、picture、picture-card
5、file-list:一般和data中的数据绑定,表示上传的文件列表
6、multiple:是否支持多选文件
7、on-change:文件状态改变时的钩子函数,在添加文件、上传成功和上传失败都会执行该函数

然后使用插槽,对图片选中后进行展示,也就是代码中间的template部分

  • 前端代码-data部分
data() {
        return {
            fileList: [],              //上传的文件列表
            avatarDialogVisible: false,   //头像框显示控制
        }
},
  • 前端代码-methods部分
methods: {
        // 自定义上传图片方法,参数必须为params
        uploadFile(params) {
            const file = params.file;
            var forms = new FormData();
            // 我这里需要将更新时间和uid同时传给后端,后端使用对象接收,所以没有设置content-type
            // 如果你只传file,要设置axios中headers的content-type为:multipart/form-data
            forms.append("file", file);
            forms.append("updatedTime", this.$utils.getNowFormatTime());
            forms.append("uid", this.user.uid);
            this.$axios({
                method: "post",
                url: "/avatar/upload",
                data: forms,
            }).then(res => {
                if (res.data.code == "200") {
                    this.$message({
                        message: '上传成功',
                        type: 'success'
                    })
                    this.avatarDialogVisible = false;
                } else {
                    this.$message({
                        message: '上传失败',
                        type: 'error'
                    })
                }
            }).catch(err => {
                console.log("上传文件时发生错误: " + err);
            })
        },
        // 上传图片时检查
        beforeAvatarUpload(file) {
            //允许的图片类型
            const imgType = (file.type === 'image/jpeg') || (file.type === 'image/png') || (file.type === 'image/gif');
            //文件大小3M
            const imgLimit= (file.size / 1024 / 1024) < 3;
            if (!imgType) {
                this.$message.error("只允许jpg、png、gif格式的图片");
                return false;
            }
            if (!imgLimit) {
                this.$message.error("上传的图片大小不能超过3MB");
                return false;
            }
            console.log("检查通过");
            return true;
        },
        //文件改变时的钩子函数,只能上传一张,选中后会覆盖掉之前的图片,
        fileChange(file, fileList) {
        	//this.file表示上一张被选中的图片,file.raw表示当前选中的图片
            this.file = file.raw;
            if (fileList.length > 0) {
                this.fileList = [fileList[fileList.length - 1]];
            }
        },
        // 确认修改头像
        handleUpdateAvatar() {
            this.$refs['upload'].submit();
            this.avatarDialogVisible = false;
            this.$refs['upload'].clearFiles();
        },
        // 取消上传头像
        cancel() {
            this.avatarDialogVisible = false;
            this.$refs['upload'].clearFiles();
        },
    }

后端代码

  • 实体类Upload-接收前端参数
@Data
public class Upload {
    private MultipartFile file;
    private String uid;
    private String updatedTime;
}
  • controller层
@PostMapping("/upload")
public Result avatar(Upload upload) throws FileNotFoundException {
    MultipartFile avatarFile = upload.getFile();
    String uid = upload.getUid();
    String updatedTime = upload.getUpdatedTime();
    if(avatarFile.isEmpty()){
        return Result.fail("文件上传失败");
    }

    // 设置文件名:uid+原文件名
    String fileName = uid + "_" + avatarFile.getOriginalFilename();
    //获取静态资源目录所在的位置路径:/项目名称/target/classes
    //注意,如果你的项目要部署到云服务器,这个方法会失效
    String path = ResourceUtils.getURL("classpath:").getPath();
    //拼接保存头像的目录路径
    File avatarDir = new File(path + "/static/upload/avatar");
    //如果文件路径不存在,就新建一个,使用mkdirs()函数,可以创建多级目录
    if(!avatarDir.exists()){
        System.out.println("正在创建/upload/avatar目录");
        avatarDir.mkdirs();
    }

    //文件保存的路径,这里的System.getProperty("file.separator")表示当前系统下的分隔符,如:"/"
    File dest = new File(avatarDir + System.getProperty("file.separator") + fileName);
    //存储在数据库中的路径
    String storePath = "/static/upload/avatar/" + fileName;

    try{
        //保存图片,transferTo()函数根据指定路径保存图片
        avatarFile.transferTo(dest);
        //更新数据库
        Avatar avatar = new Avatar();
        avatar.setUid(Integer.valueOf(uid));
        avatar.setAvatar(storePath);
        avatar.setUpdateTime(updatedTime);
        //成功返回图片的路径,用于前端图片展示
        return avatarService.saveOrUpdate(avatar)?Result.success(1, storePath):Result.fail("文件上传失败");
    }catch(IOException e){
        e.printStackTrace();
        return Result.fail("文件上传失败");
    }
}

效果演示

在这里插入图片描述

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值