当前位置:网站首页>3.用户上传头像
3.用户上传头像
2022-08-02 14:10:00 【鱼子酱:P】
还是三层架构,首先考虑数据访问层,这一层没有什么处理,因为是把头像存到硬盘里没有存到数据库里;业务层需要就是上传完头像后更新headurl,服务端就需要提供一个改变头像路径的功能;上传文件这个事就在controller表现层里实现就好了。因为啊MultipartFile是属于表现层的一个对象,要是传给了service就产生了耦合了,不太合适。
首先上传头像得有一个存储头像的路径,这个路径不能是固定的,因为在本地开发和部署到服务器肯定不一样,目前存到本地,后期也会存到云服务器上。在application.properties里配上头像上传路径。
1. 大体思路
①用户点击首页面【账号设置】按钮,getSettingPage()会返回静态资源【/site/setting】,进入到设置页面,执行UserController的控制器方法;
②我们点击【上传头像】按钮后,发送【/user/upload】,执行UserController的控制器方法uploadHeader():首先对空值进行处理,然后用substring分割出文件后缀,png或者jpg等等。如果没有后缀就提示文件格式不正确。对用户上传的图片重命名,用之前写的生成uuid的方法加上分割出来的文件后缀。将文件存储到我们在配置文件中设置的路径下,并更新当前user的headerUrl属性为指定格式的路径;
③当我们需要访问头像(即user的headerUrl属性)时,控制器方法getHeader()会根据headerUrl,将对应目录下的头像复制出来。
2. 用户控制器-上传头像
这里用到的是Spring MVC的multipartFile,头像的存储和获取直接在controller层操作。新建一个UserController。将类的访问路径设为/user。
转载:初步理解MultipartFile - 简书 (jianshu.com)
MultipartFile是SpringMVC提供简化上传操作的工具类。
在不使用框架之前,都是使用原生的HttpServletRequest来接收上传的数据,文件是以二进制流传递到后端的,然后需要我们自己转换为File类。使用了MultipartFile工具类之后,我们对文件上传的操作就简便许多了。
MultipartFile主要是用表单的形式进行文件上传,在接收到文件时,可以获取文件的相关属性,比如文件名、文件大小、文件类型等等。
- 第一个方法,用于返回个人设置页面,直接返回模板路径。
- 然后上传头像的方法,这里从容器获取两个对象,一个是MultiparFile,也就是从浏览器传过来的头像文件,一个是model,用于模型返回信息。
- 首先对空值进行处理,然后用substring分割出文件后缀,png或者jpg等等。如果没有后缀就提示文件格式不正确。对用户上传的图片重命名,用之前写的生成uuid的方法加上分割出来的文件后缀。
- 再在我们指定的文件存放位置新建一个文件,文件名使用生成的名字,并记录异常,将异常向上抛出,用于之后的处理。然后从hostHolder里获取当前用户,更新头像路径。
package com.nowcoder.mycommunity.controller;
@Controller
@RequestMapping("/user")
public class UserController {
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
//注入文件的上传路径
@Value("${community.path.upload}")
private String uploadPath;
//注入域名
@Value("${mycommunity.path.domin}")
private String domain;
//访问路径
@Value("${server.servlet.context-path}")
private String contextPath;
@Autowired
private UserService userService;
@Autowired
private HostHolder hostHolder;
//进入账号设置
@RequestMapping(path="/setting",method = RequestMethod.GET)
public String getSettingPage(){
return "/site/setting";
}
//上传头像
@RequestMapping(path = "/upload", method = RequestMethod.POST)
public String uploadHeader(MultipartFile headerImage, Model model){
//如果没上传头像,就点击上传头像按钮
if(headerImage == null){
model.addAttribute("error","您还没有选择图片!");
return "/site/setting";
}
//获取图片后缀名
String fileName = headerImage.getOriginalFilename();
String suffix = fileName.substring(fileName.lastIndexOf("."));
if(StringUtils.isBlank(suffix)){ //如果后缀名为空
model.addAttribute("error","文件格式不正确!");
return "/site/setting";
}
//生成随机的文件名
fileName = CommunityUtil.generateUUID() + suffix;
File dest = new File(uploadPath + "/" + fileName);
try {
headerImage.transferTo(dest);
} catch (IOException e) {
logger.error("上传文件失败:" + e.getMessage());
throw new RuntimeException("上传文件失败,服务器发生异常!", e);
}
//到此就可以正常进行了
//更新当前用户头像的路径(Web访问路径)
//格式:http://localhost:8080/community/user/header/xxx.png
User user = hostHolder.getUser();
String headerUrl = domain + contextPath + "/user/header/" + fileName;
userService.updateHeader(user.getId(), headerUrl);
return "redirect:/index";
}
//获取头像(和上面头像设置时的路径格式保持一致)
@RequestMapping(path = "/header/{fileName}", method = RequestMethod.GET)
public void getHeader(@PathVariable("fileName") String fileName, HttpServletResponse response){
//服务器存放路径
fileName = uploadPath + "/" + fileName;
//文件后缀
String suffix = fileName.substring(fileName.lastIndexOf("."));
//响应图片(浏览器响应图片时,为此写法)
response.setContentType("image/" + suffix);
//获取字节流
try (
//此为java7写法,这里面声明的变量会自动加finally,在里面自动关闭
//而输出流会被SpringMVC自动关闭
FileInputStream fis = new FileInputStream(fileName);
OutputStream os = response.getOutputStream();
){
byte[] buffer = new byte[1024];
int b = 0;
while((b = fis.read(buffer)) != -1){
os.write(buffer, 0, b);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3. 更新用户头像方法
在UserService类中添加方法
还是从dao层向controller开发,由于头像直接存在本地,没有存到数据库,这里不涉及dao层。
service层主要处理user表里的headUrl,这个方法在userMapper里写过,直接调用就可以。
//更新用户头像
public int updateHeader(int userId, String headurl){
return userMapper.updateHeader(userId, headurl);
}
4. 配置文件
添加文件的上传存储路径。
# 上传资源存放的位置
community.path.upload=e:/nowcoder/data/upload
5. html
①首页index.html:进入【账号设置】。
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item text-center" href="site/profile.html">个人主页</a>
<a class="dropdown-item text-center" th:href="@{/user/setting}">账号设置</a>
<a class="dropdown-item text-center" th:href="@{/logout}">退出登录</a>
<div class="dropdown-divider"></div>
<span class="dropdown-item text-center text-secondary" th:utext="${loginUser.username}">nowcoder</span>
</div>
②账号设置页面setting.html:上传头像
<!-- 上传头像 -->
<h6 class="text-left text-info border-bottom pb-2">上传头像</h6>
<form class="mt-5" method="post" enctype="multipart/form-data" th:action="@{/user/upload}">
<div class="form-group row mt-4">
<label for="head-image" class="col-sm-2 col-form-label text-right">选择头像:</label>
<div class="col-sm-10">
<div class="custom-file">
<!-- name需要与控制器方法中形参名相同 -->
<input type="file" th:class="|custom-file-input ${error!=null?'is-invalid':''}|"
id="head-image" name="headerImage" lang="es" required="">
<label class="custom-file-label" for="head-image" data-browse="文件">选择一张图片</label>
<div class="invalid-feedback" th:text="${error}">
该账号不存在!
</div>
</div>
</div>
</div>
<div class="form-group row mt-4">
<div class="col-sm-2"></div>
<div class="col-sm-10 text-center">
<button type="submit" class="btn btn-info text-white form-control">立即上传</button>
</div>
</div>
</form
边栏推荐
猜你喜欢
cmake配置libtorch报错Failed to compute shorthash for libnvrtc.so
Win7怎么干净启动?如何只加载基本服务启动Win7系统
Win10系统设置application identity自动提示拒绝访问怎么办
Mysql连接错误解决
二叉树遍历之后序遍历(非递归、递归)入门详解
Spark及相关生态组件安装配置——快速回忆
golang之GMP调度模型
What is Win10 God Mode for?How to enable God Mode in Windows 10?
Win10 cannot directly use photo viewer to open the picture
为vscode配置clangd
随机推荐
TCP三次握手、四次挥手
Mysql连接错误解决
Win11没有本地用户和组怎么解决
FP5207电池升压 5V9V12V24V36V42V大功率方案
Win10 cannot directly use photo viewer to open the picture
Network Security Packet Capture
win10系统更新错误代码0x80244022怎么办
LORA芯片ASR6505无线远距离传输8位MCU
Mysql lock
FP7195芯片PWM转模拟调光至0.1%低亮度时恒流一致性的控制原理
Win10系统设置application identity自动提示拒绝访问怎么办
Please make sure you have the correct access rights and the repository exists.问题解决
FP7195降压恒流PWM转模拟调光零压差大功率驱动方案原理图
How to solve Win11 without local users and groups
2022TI杯D题混沌信号产生实验装置
DP1332E内置c8051的mcu内核NFC刷卡芯片国产兼容NXP
A clean start Windows 7?How to load only the basic service start Windows 7 system
Impressions of Embrace Jetpack
cmake configure libtorch error Failed to compute shorthash for libnvrtc.so
MATLAB绘图函数ezplot入门详解