赞
踩
请注意,项目使用vue3 + Element-Plus 2.3.7 + springboot 2.7.8!
element-plus提供了el-upload组件实现头像上传,具体的属性说明请参考官方文档
组件拿到用户上传的图片之后,首先需要展示,用户确认后再传输给后端,后端接收图片资源后进行保存,并将保存状态返回给前端。
<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() {
return {
fileList: [], //上传的文件列表
avatarDialogVisible: false, //头像框显示控制
}
},
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(); }, }
@Data
public class Upload {
private MultipartFile file;
private String uid;
private String updatedTime;
}
@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("文件上传失败"); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。