
4.3 文件上传
Spring MVC对文件上传做了简化,在Spring Boot中对此做了更进一步的简化,文件上传更为方便。
Java中的文件上传一共涉及两个组件,一个是CommonsMultipartResolver,另一个是StandardServletMultipartResolver,其中CommonsMultipartResolver使用commons-fileupload来处理multipart请求,而StandardServletMultipartResolver则是基于Servlet 3.0来处理multipart请求的,因此若使用StandardServletMultipartResolver,则不需要添加额外的jar包。Tomcat 7.0开始就支持Servlet 3.0了,而Spring Boot 2.0.4内嵌的Tomcat为Tomcat 8.5.32,因此可以直接使用StandardServletMultipartResolver。而在Spring Boot提供的文件上传自动化配置类MultipartAutoConfiguration中,默认也是采用StandardServletMultipartResolver,部分源码如下:

根据这里的配置可以看出,如果开发者没有提供MultipartResolver,那么默认采用的MultipartResolver就是StandardServletMultipartResolver。因此,在Spring Boot中上传文件甚至可以做到零配置。下面来看具体上传过程。
4.3.1 单文件上传
首先创建一个Spring Boot项目并添加spring-boot-starter-web依赖。
然后在resources目录下的static目录中创建一个upload.html文件,内容如下:

这是一个很简单的文件上传页面,上传接口是/upload,注意请求方法是post,enctype是multipart/form-data。
接着创建文件上传处理接口,代码如下:

代码解释:
• 第6~12代码表示规划上传文件的保存路径为项目运行目录下的uploadFile文件夹,并在文件夹中通过日期对所上传的文件归类保存。
• 第13~15行代码表示给上传的文件重命名,这是为了避免文件重名。
• 第17行是文件保存操作。
• 第18~20行是生成上传文件的访问路径,并将访问路径返回。
最后在浏览器中进行测试。
运行项目,在浏览器中输入“http://localhost:8080/upload.html”进行文件上传,如图4-5所示。

图4-5
单击“请选择文件”按钮上传文件,文件上传成功后,会返回上传文件的访问路径,如图4-6所示。

图4-6
用这个路径就可以看到刚刚上传的图片,如图4-7所示。

图4-7
在4.2节中向读者介绍过静态资源位置除了classpath下面的4个路径之外,还有一个" /",因此这里的图片虽然是静态资源却可以直接访问到。
至此,一个简单的图片上传逻辑就完成了,对于开发者而言,只需要专注于图片上传的业务逻辑,而不需要在配置上花费太多时间。
当然,如果开发者需要对图片上传的细节进行配置,也是允许的,代码如下:

代码解释:
• 第1行表示是否开启文件上传支持,默认为true。
• 第2行表示文件写入磁盘的阈值,默认为0。
• 第3行表示上传文件的临时保存位置。
• 第4行表示上传的单个文件的最大大小,默认为1MB。
• 第5行表示多文件上传时文件的总大小,默认为10MB。
• 第6行表示文件是否延迟解析,默认为false。
4.3.2 多文件上传
多文件上传和单文件上传基本一致,首先修改HTML文件,代码如下:

然后修改控制器,代码如下:

控制器里边的核心逻辑和单文件上传是一样的,只是多一个遍历的步骤。