MultipartFile 只能封装单个文件。 可以处理上传的文件。但是上传的文件可以不采用MultipartFile 的方式。可以采用其他方式处理。
表单的处理必须要用 enctype=“multipart.form-data”。并采用post提交
访问设置界面
- 在UserController中设置访问链接,
@Controller @RequestMapping("/user") public class UserController { @RequestMapping(path = "/setting", method = RequestMethod.GET) public String getSettingPage(){ return "/site/setting"; } }
- 修改对应HTML,(setting和对应index的header)
<a class="dropdown-item text-center" th:href="@{/user/setting}">账号设置</a>
上传获取头像
- 在配置application.properties文件中配置上传资源时存放的路径。
community.path.upload=D:/Project/workspace/file
-
考虑数据访问层DAO(暂时不需要动)
-
Service业务层
- 更新用户的headerUrl
/** * 更新用户头像 */ public int updateHeaderUrl(int userId, String url){ return userMapper.updateHeader(userId,url); }
- 更新用户的headerUrl
-
Controller
-
上传头像。上传存储的路径、服务器路径、项目路径、获取当前对象hostHoder
Logger logger = LoggerFactory.getLogger(UserController.class); @Value("${community.path.upload}") private String uploadPath; @Value("${community.path.domain}") private String domain; @Value("${server.servlet.context-path}") private String contextPath;
@Autowired UserService userService ; @Autowired HostHolder hostHolder; //取当前的用户对象 /** * 处理上传文件的请求 */ @RequestMapping(path = "/upload", method = RequestMethod.POST) public String uploadHeader (MultipartFile headerImg, Model model){ if(headerImg ==null){ model.addAttribute("error","您还未选择上传图片"); return "/site/setting"; } //为了避免覆盖,文件名要加一个随机字符。同时要保证后缀名不变,因此需要先得到后缀名,暂存一下、 String filename = headerImg.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 { headerImg.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 headUrl =domain + contextPath + "/user/header/"+ filename; userService.updateHeaderUrl(user.getId(),headUrl); return "redirect:/index"; }
上传图像的过程(MultipartFile 上传文件):
-
判空
-
判合法
-
上传
-
获取图片的后缀名, 修改图片名保证唯一。
-
获取当前用户对象 ,设置图片上传路径。
- 调Service上传
-
-
-
获取头像
/** * 获取头像 */ @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 ( OutputStream os = response.getOutputStream(); //获取字节流,输出流 FileInputStream fis = new FileInputStream(fileName); ){ //建立缓存区输出 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()); } }
放在try()内的留,Java编译器会自动创建finnal帮我们关闭。
FileInputStream 创建文件的输入流,用来读文件filename。进行批量输出,而不是按照字节输出来提高效率。 所以从 fis---->buffer---->os(respond)- 获取头像过程
- 服务器路径解析
- 文件名后缀解析
- 设置respose的输出格式
- 从文件中读数据到缓冲区,再到response对象中。
- 获取头像过程
-
处理对应HTML
<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"> <input type="file" th:class="|custom-file-input ${error==null?'':'is-invalid'}|" id="head-image" name="headerImg" 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>
-
遇错:
There was an unexpected error (type=Internal Server Error, status=500).
上传文件失败,服务器发生异常!
java.lang.RuntimeException: 上传文件失败,服务器发生异常!
Caused by: java.io.IOException: java.io.FileNotFoundException: C:UserslilyAppDataLocalTemp omcat.8080.4074473235196648822workTomcatlocalhostcommunitycommunity.path.upload1c0208b7cd0c47d3898b698545693ae1.jpg (系统找不到指定的路径。)
原因是因为写 忘记加${} ,
@Value("community.path.upload")
private String uploadPath;
@Value("community.path.domain")
private String domain;
@Value("server.servlet.context-path")
private String contextPath;
修改后 成功。
@Value("${community.path.upload}")
private String uploadPath;
@Value("${community.path.domain}")
private String domain;
@Value("${server.servlet.context-path}")
private String contextPath;
如果没有建立对应的文件夹,也会报找不到路径的错。需要手动创建对应目录。