参考牛客网高级项目教程
1. 账号设置功能需求
2. 上传文件模块开发
2.1 账号设置页面显示
1)Controller层处理新请求
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(value = "/setting", method = RequestMethod.GET)
public String getUserSetting(){
return "/site/setting";
}
}
2)View视图层处理模板页面
-
处理动态url,测试结果:
2.2 上传头像
1)配置
2)service层,更改用户头像
-
有关用户的操作,dao层已经处理好了,暂时不需要动 -
上传头像后,用户头像需要更改,因此,需要在service层修改业务
public int updateHeader(int userId, String headerUrl) {
return userMapper.updateHeader(userId, headerUrl);
}
3)Controller层处理上传请求
- 1.使用MultipartFile接受用户上传文件,并将文件重命名后保存到服务端指定位置
- 2.更新数据库,将用户更改的头像数据更新
- 3.判断操作是否正确,
- 不正确,返回用户设置页面,并显示错误提示信息
- 正确,重定向到首页,显示更新后的用户头像
1.将上传的文件保存到服务端
MultipartFile
-
多组件文档,spring框架下的一个包,封装了很多api,方便操作文件流的上传处理
- MultipartFile是一个接口,并继承自InputStreamSource
- 我们在使用MultipartFile作为参数传递的时候,
- 可以将MultipartFile声明为一个数组,这样就能支持多文件传输,
- 如果只需要传输一个文件,则去掉数组就好了
-
因此,controller方法中,将MultipartFile作为参数传入
@RequestMapping(path = "/upload", method = RequestMethod.POST)
public String uploadHeader(MultipartFile multipartFile, Model model) {
return "redirect:/index";
}
-
通过MultipartFile接受上传的文件,要先判空
getOriginalFilename()
substring(filename.lastIndexOf(’.’))
new File(address)
transferTo(dest)
-
将上传文件写入到指定路径文件中,此方法有重载,也可以写到指定路径中
try {
multipartFile.transferTo(dest);
} catch (IOException e) {
logger.error("上传文件失败!" + e.getMessage());
throw new IllegalArgumentException("上传文件失败,服务器发生异常!", e);
}
2.更新数据库
-
上传头像成功后,要将用户头像的数据更改 -
最后重定向到首页,展示新的用户信息
String headerUrl = domain + contextPath + "/user/header" + "/" + filename;
User user = hostHolder.getUser();
userService.updateHeader(user.getId(), headerUrl);
return "redirect:/index";
-
完整代码如下:
@RequestMapping(path = "/upload", method = RequestMethod.POST)
public String uploadHeader(MultipartFile multipartFile, Model model) {
if(multipartFile == null) {
model.addAttribute("error", "您还没有选择图片!");
return "/site/setting";
}
String filename = multipartFile.getName();
String suffix = filename.substring(filename.lastIndexOf('.'));
if(StringUtils.isBlank(suffix)) {
model.addAttribute("error", "文件格式不正确!");
return "/site/setting";
}
filename = CommunityUtil.generateUUID() + suffix;
String address = uploadPath + "/" + filename;
File dest = new File(address);
try {
multipartFile.transferTo(dest);
} catch (IOException e) {
logger.error("上传文件失败!" + e.getMessage());
throw new IllegalArgumentException("上传文件失败,服务器发生异常!", e);
}
String headerUrl = domain + contextPath + "/user/header" + "/" + filename;
User user = hostHolder.getUser();
userService.updateHeader(user.getId(), headerUrl);
return "redirect:/index";
}
4)Controller处理访问headerUrl请求
-
目的是将上一步设定的用户web访问的url路径能够在浏览器中显示出来 -
因此,需要处理这个请求
- 获取用户头像请求,访问路径即之前设置的路径,
- 服务端一段从内存文件里读,一端写给浏览器
-
如果单独访问url请求,本质上也是向浏览器下载文件
@RequestMapping(value = "/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 (
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) {
logger.error("读取头像失败: " + e.getMessage());
}
}
5)处理模板页面
表单头部处理
enctype=“multipart/form-data”
-
要添加能够支持multipart类接受文件的支持 <form class="mt-5" method="post" enctype="multipart/form-data" th:action="@{/user/upload}">
-
添加错误信息 <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>
注意事项:
-
1.MultipartFile类对像命名不能为multipartFile,否则接收不到上传的文件
- pring-boot自带的org.springframework.web.multipart.MultipartFile
和Multipart产生冲突 -
2.MultipartFile获取文件的名称是getOriginalFilename()方法,不是getName()方法
- getOriginalFileName方法获取的是文件的完整名称,包括文件名称+文件拓展名
- getName方法获取的是前后端约定的传入文件的参数的名称,即自己定义的类名headerImage
-
3.@Value("${community.path.upload}"),
测试结果
|