1、访问账号设置页面
用户相关逻辑、UserController
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(path = "/setting", method = RequestMethod.GET)
public String getSettingPage() {
return "/site/setting";
}
}
setting.html:配置thymeleaf.org、静态资源路径、header复用首页header
index.html:设置动态链接
2、上传头像
1、配置文件配置上传路径
2、从数据访问层(存到硬盘,不用写),表现层实现controller更新headerUrl的功能。
业务层写UserService
public int updateHeader(int userId, String headerUrl) {
return userMapper.updateHeader(userId, headerUrl);
}
2、UserController
SpringMVC通过MultipartFile处理上传文件,为了避免耦合就在UserController上实现,不去service层了。
日志
注入上传路径、域名、项目访问路径、userService、hostHolder
上传表单必须为Post
判空
截取后缀、暂存后缀
生成随机文件名
给文件存放路径,初始化文件(uploadPath),写入,抛异常
更新用户头像路径(Web访问路径)
重定向到首页
@Controller
@RequestMapping("/user")
public class UserController {
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
@Value("${community.path.upload}")//value注入固定的值
private String uploadPath;
@Value("${community.path.domain}")
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);//怎么统一处理Controller异常
}
// 更新用户头像路径(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";
}
3、获取头像
1、UserController
向浏览器响应图片,向浏览器响应的不是网页也不是字符串,而是图片,是二进制的数据,通过流手动向浏览器输出,手动调用response往外写,返回类型是void。
//向浏览器响应图片,向浏览器响应的不是网页也不是字符串,而是图片,是二进制的数据,通过流手动向浏览器输出,手动调用response往外写,返回类型是void。
@RequestMapping(path = "/header/{fileName}", method = RequestMethod.GET)//二进制数据,通过流,不是网页不是图片,手动调response往外写
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);//输入流,需要手动关闭,放在try()里,finally里面close
ServletOutputStream os = response.getOutputStream();//输出流,SpringMVC帮我们关闭
){
byte[] buffer = new byte[1024];//缓冲 1024个字节
int b = 0;//游标
while ((b = fis.read(buffer)) != -1) {//读到数据了,==-1没读到数据
os.write(buffer,0, b);
}
} catch (IOException e) {
logger.error("读取头像失败:" + e.getMessage());
}
}
2、setting.html处理表单:
form:
<form class="mt-5" method="post" enctype="multipart/form-data" th:action="@{/user/upload}">
name和controller匹配name="headerImage"
,动态错误提示th:class="|custom-file-input ${error!=null?'is-invalid':''}|"
,只有在error!=null
时,有下面的样式。
<div class="custom-file">
<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}">
该账号不存在!这里被${error}覆盖了其实是不显示的
</div>
</div>