SpringBoot+Vue+ElementUI实现头像上传
- 1.基础知识(补充)
- 2.后端依赖导入Maven
- 3.后端Controller代码(核心)
- 4.配置代码(核心)
- 5.前端代码
- 6.总结
1.基础知识(补充)
File协议:
FIle协议也叫本地文件传输协议 ,主要用于访问本地计算机中的文件,就如同在Windows资源管理器中打开文件或者通过右键单击‘打开’一样。即File协议是访问你本机的文件资源。
要使用File协议,基本的格式如下:file:///文件路径。
2.后端依赖导入Maven
这里使用到了hutool工具,很好用,不过建议新手多了解底层,在使用工具
<!-- 文件上传工具类 --><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version></dependency>
<!-- hutool 工具类 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.8</version></dependency>
3.后端Controller代码(核心)
看不懂代码请认真看代码上面的注释,写的比较详细了,如果有什么不懂的,或者有什么问题,可以在评论区指出,都会回答的!!!为的就是共同学习!!!
这个项目我用到的是SpringSecurity,然后通过一个BaseController封装了SecurityContextHolder来获取当前登录用户的信息,其次就是用到了一些定义好的变量
将上传的文件通过前端表单传给后端,后端通过file.transferTo()方法下载到本地
@PostMapping("/avatar")public R<Map<String,Object>> avatar(MultipartFile file) throws IOException {// 获取当前登录用户LoginUser loginUser = getLoginUser();// 文件名称 时间日期+文件名_uuid+后缀String fileName = StrUtil.format("{}/{}_{}.{}", DateUtil.format(DateUtil.date(),"yyy/MM/dd"), FilenameUtils.getBaseName(file.getOriginalFilename()),DateUtil.format(new Date(),"yyyyMMdd")+ IdUtil.fastUUID(),FilenameUtils.getExtension(file.getOriginalFilename()));// 父目录String baseDir = WenJianConfig.getAvatarPath();//路径拼接File desc = new File(baseDir + File.separator + fileName);if (!desc.exists()){if (!desc.getParentFile().exists()){desc.getParentFile().mkdirs();}}// 下载file.transferTo(desc);int dirLastIndex = WenJianConfig.getProfile().length() + 1;// 截取upload/下的名称存入数据库String currentDir = baseDir.substring(dirLastIndex);// /profile/avatar/2022/10/10/293a05e068a7dfb298c87238de858130_2022101031242e4a-079a-4d4b-9c5c-139f5d2152ab.jpeg// Constants.RESOURCE_PREFIX = "/profile";String avatar = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;// 修改数据库中的头像路径iSysUserService.updateUserAvatar(loginUser.getUser().getUsername(),avatar);Map<String, Object> map = new HashMap<>();// 将头像路径返回,这里是为了头像上传后有一个回显的效果map.put("imgUrl",avatar);// 将缓存中的对象信息进行一个更新loginUser.getUser().setAvatar(avatar);tokenUtil.setLoginUser(loginUser);return R.ok(map);}
4.配置代码(核心)
在application.yml中配置本地保存的路径,后面想改下载的路径可以直接在配置文件中修改
# 项目相关配置
wenjian:# 文件路径 示例( Windows配置D:/wenjian/uploadPath,Linux配置 /home/wenjian/uploadPath)profile: D:/wenjian/uploadPath
获取yml中配置路径的属性值
package com.sky.common.config;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;/*** @author 尹稳健~* @version 1.0* @time 2022/10/9*/
@Component
@ConfigurationProperties(prefix = "wenjian")
public class WenJianConfig {/** 上传路径 */private static String profile;public static String getProfile() {return profile;}public void setProfile(String profile) {WenJianConfig.profile = profile;}/*** 获取导入上传路径*/public static String getImportPath(){return getProfile() + "/import";}/*** 获取头像上传路径*/public static String getAvatarPath(){return getProfile() + "/avatar";}/*** 获取下载路径*/public static String getDownloadPath(){return getProfile() + "/download/";}/*** 获取上传路径*/public static String getUploadPath(){return getProfile() + "/upload";}
}
这个时候就有人会问如何进行一个头像回显?
就拿这个路径进行举例:
/profile/avatar/2022/10/10/293a05e068a7dfb298c87238de858130_2022101031242e4a-079a-4d4b-9c5c-139f5d2152ab.jpeg
凭什么网页拿着这玩意可以直接展示出来一张图片?
因为在后端这里进行一个路径映射
@Configuration
public class MyWebConfigurer implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {/** 本地文件上传路径 */// Constants.RESOURCE_PREFIX = "/profile"// WenJianConfig.getProfile() = 你本地存储的位置registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + WenJianConfig.getProfile() + "/");}}
图片展示在网页上
5.前端代码
前端使用的是Vue+ElementUI,所以我只截图关键代码,谢谢!!
参数解读:
- action:是必须指定的,这对应着你后端的接口。
- headers:我这里为什么指定了呢?一开始我是没有指定,但是我发现如果你不指定,那么你通过点击确定按钮后,后端不会进行一个响应,因为SpringSecurity把他拦截下来了,因为你本次请求没有携带token信息,所以这里我添加了一个headers。
- on-success:这个也是关键参数,文件上传成功时的钩子,将上传的文件流传给后端进行接收,后端再将数据进行响应回前端 。
<el-uploadclass="avatar-uploader"action="http://localhost:8080/manage/sys/user/avatar":show-file-list="false":on-success="handleAvatarSuccess":before-upload="beforeAvatarUpload":headers="headerObj"><img v-if="avatar" :src="avatar" class="img-circle img-lg" /><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload><script>
export default {
methods: {handleAvatarSuccess(res, file) {let formData = new FormData();// 将文件传给后端下载formData.append("file", file);this.$message.success(res.msg);this.avatar = "http://localhost:8080" + res.data.imgUrl;// 将数据保存再vuex中this.$store.commit("setAvatar", this.avatar);},beforeAvatarUpload(file) {const isJPG = file.type === "image/jpeg";const isLt2M = file.size / 1024 / 1024 < 2;if (!isJPG) {this.$message.error("上传头像图片只能是 JPG 格式!");}if (!isLt2M) {this.$message.error("上传头像图片大小不能超过 2MB!");}return isJPG && isLt2M;},},
}
</script>
6.总结
- 文件上传不难,关键点在前端接收文件,然后将文件传给后端,后端将文件通过流的方式下载到指定的位置。
- 稍微难一点的地方就是图片回显,只需要将本地的路径返回给前端就行通过file:/文件路径,的方式进行一个图片的回显