概述
每次说起文件上传,就不得不提一下前端的实现方式,说来也奇怪,本博主最热门的博客居然也是文件上传,3万多的访问量占了总访问量的一多半:《传统form表单提交方式的文件上传与文件存储》,而且,今天搜索“form表单提交文件” 百度第一篇居然就是这篇自己写的文章(下图留个纪念,不知道以后会不会有变化 哈哈)

但是由于这篇文章写得比较早,博客玩的还不6,文章排版很糟糕,因此自己都不愿意看,今天完成了一个类似的功能:用户头像上传,特此重写一篇,巩固记忆。
本功能涉及到的几个知识点:
1、controller层的接收方式
2、IO流相关的文件保存处理(路径问题、写出方式)
3、spring boot 自带tomcat上传文件最大值限制的设置
4、分系统分路径(Windows 或 Linux)
5、文件保存的常规实现思路
实现过程
控制器接收方式
以全栈的角度来分析这个功能,当然少不了前端的实现,但是目前多以前后端分离的方式来开发功能,因此,本篇博客着重讲解后端的spring boot的写法,这是本人认为比较工整的写法,对于前端的实现,可以看本篇博客的补充篇《传统form表单提交方式的文件上传与文件存储》。
Controller的接收方式如下:
@ApiOperation(value = "设置用户头像", notes = "设置当前用户头像") @PutMapping("/profiles") public SystemResult setUserProfile(@RequestParam(required = true) MultipartFile profile) { return userService.updUserProfile(profile); }
请求方式是PUT,required = true,参数类型为MutipartFile ,只要是Spring 生态的应用程序,文件的接收都是使用MutipartFile这个类型,它表示通过 mutipart 请求上传了的一个文件。如果多个文件上传,那就用数组,如 MutipartFile[] 。
Service处理
Controller接收到文件后,Service需要完成两个大方向的处理:1、保存文件;2、路径存库
@Override public SystemResult updUserProfile(MultipartFile newProfile) { // 根据Windows和Linux配置不同的头像保存路径 String OSName = System.getProperty("os.name"); String profilesPath = OSName.toLowerCase().startsWith("win") ? SystemConstant.WINDOWS_PROFILES_PATH : SystemConstant.LINUX_PROFILES_PATH; if (!newProfile.isEmpty()) { // 当前用户 User currentUser = (User) SecurityUtils.getSubject().getPrincipal(); String profilePathAndNameDB = userDao.selectUserById(currentUser.getUserId()).getProfilePath(); // 默认以原来的头像名称为新头像的名称,这样可以直接替换掉文件夹中对应的旧头像 String newProfileName = profilePathAndNameDB; // 若头像名称不存在 if (profilePathAndNameDB == null || "".equals(profilePathAndNameDB)) { newProfileName = profilesPath+ System.currentTimeMillis()+ newProfile.getOriginalFilename(); // 路径存库 currentUser.setProfilePath(newProfileName); userDao.updateUserProfilePath(currentUser); } // 磁盘保存 BufferedOutputStream out = null; try { File folder = new File(profilesPath); if (!folder.exists()) folder.mkdirs(); out = new BufferedOutputStream(new FileOutputStream(newProfileName)); // 写入新文件 out.write(newProfile.getBytes()); out.flush(); } catch (Exception e) { e.printStackTrace(); return new SystemResult(HttpStatus.OK.value(), "设置头像失败", Boolean.FALSE); } finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } return new SystemResult(HttpStatus.OK.value(), "设置头像成功", Boolean.TRUE); } else { return new SystemResult(HttpStatus.OK.value(), "设置头像失败", Boolean.FALSE); } }
注释写的比较细,文件的命名,以及目录的创建,也不需要多说什么了。
关于两个系统中使用的路径,虽然Windows系统中都是使用反斜杠“\” ,但是在Java中反斜杠需要转义,比如:“C:\\用户\\文件夹\\文件.txt”,这样,在存入数据库的时候也会比较难看,后来经过测试发现在Java中使用“/”也是没问题的。上述代码两个路径常量如下:
/ 头像保存路径 */ public static final String WINDOWS_PROFILES_PATH = "C:/super_meeting/profiles/"; public static final String LINUX_PROFILES_PATH = "/root/super_meeting/profiles/";
另外,当前用户的获取是通过shiro中的安全管理器SecurityManager来取得的,我们也可以让页面传入一个用户的ID(如果页面知道的话)这样就适用于任何使用场景了。
修改文件上传限制
如果做到上一步,当你上传的文件过大,可能总是会报如下异常:
org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field profile exceeds its maximum permitted size of bytes.
可以看到这是Spring Boot自带的tomcat对上传文件大小的限制,我们需要增加一个配置信息:
@Configuration public class CommonConfiguration { / * 文件上传配置,在application配置文件中设置不起作用! */ @Bean public MultipartConfigElement multipartConfigElement() { MultipartConfigFactory factory = new MultipartConfigFactory(); // 单个文件最大 factory.setMaxFileSize("10240KB"); // KB,MB // 设置总上传数据总大小 factory.setMaxRequestSize("KB"); return factory.createMultipartConfig(); } }
网上还有直接写在application.properties文件中的方式,但是本人亲测不管用,虽然不是很喜欢这种配置类的书写方式,但也没什么办法,凑合着用吧。
配置文件的写法如下,如果哪位测试可用的话,请文末留言告诉我!!!文末留言告诉我!!!告诉我!!!
spring.http.multipart.maxFileSize = 10Mb
spring.http.multipart.maxRequestSize=100Mb
测试
查询数据库:

打开swagger选择一张图片,或者你自己写一个form表单,都可以。


检查一下 系统盘:

数据库:

完美!!
综上,就是文件上传的全过程,其中省略了DAO层的代码,不过这个不是重点,重点还是我在概述中列出的那几项。如果有任何问题,请文末留言。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/214279.html原文链接:https://javaforall.net
