在应用系统中,文件上传是非常常用的系统功能,spring mvc为上传文件提供了良好的支持。首先spring mvc的文件上传是通过MultipartResolver(Multipart解析器)处理的,对于MultipartResolver而言它只是一个接口,它有两个实现类。
- CommonsMultipartResolver:依赖于Apache下的fileupload项目解析Multipart请求。需要依赖第三方包。
- StandardServletMultipartResolver:依赖于Servlet3.0或者更高版本。不用依赖于第三方包。spring 3.1后支持。
StandardServletMultipartResolver上传
java配置MultipartResolver
@Bean
public MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
StandardServletMultipartResolver构造方法没有参数,很容易进行实例化,这样通过@Bean注解便可以了,需要注意的是,没有给Bean指定名称,那么默认会以方法名作为Bean的名称,multipartResolver是是spring约定好的Bean name,不可以更改,如果方法名不一致,需要指定@Bean(name = "multipartResolver")。有时候还要对上传文件进行配置,比如限制单个文件的大小,设置上传文件的路径等等。
StandardServletMultipartResolver需要通过servlet容器配置启用servlet 3.0 multipart解析,分析servlet3.0规范允许没有web.xml配置,只需要使用注解就可以了。spring3.1之后的版本也提供了注解方式的配置, 该方式需要继承AbstractAnnotationConfigDispatcherServletInitializer类,然后实现它所定义的方法。
package com.wise.tiger;
import javax.servlet.Filter;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletRegistration.Dynamic;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.wise.tiger.config.RootConfig;
import com.wise.tiger.config.Swagger2Config;
import com.wise.tiger.config.WebConfig;
/**
* servlet3.0规范允许没有web.xml配置,只需要使用注解就可以了
* spring3.1之后的版本也提供了注解方式的配置
* 该方式需要继承AbstractAnnotationConfigDispatcherServletInitializer类,然后实现它所定义的方法。
* @Description:
* @author: <a href="mailto:1020zhaodan@163.com">Adan</a>
* @date: 2019年5月28日 上午9:43:01
* @version:1.0-snapshot
* servlet3.0之后的版本允许动态加载servlet,只是按照规范需要实现ServletContainerInitializer接口。
* 于是spring mvc在自己的包内实现了一个类SpringServletContainerInitializer,它实现了ServletContainerInitializer接口,
* 这样就能够通过它去加载我们提供的WebAppInitializer类
*/
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
/**
* Spring IoC(root)容器配置
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] {RootConfig.class};
}
/**
* DispatcherServlet的URI映射关系配置
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] {WebConfig.class,Swagger2Config.class};
}
/**
* dispatcherServlet 拦截内容(什么请求交给前端控制器)
* <url-pattern>/</url-pattern>
*/
@Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
/**
* 添加过滤器Filter
*/
@Override
protected Filter[] getServletFilters() {
return new Filter[] {
new CharacterEncodingFilter("UTF-8", true, true)//spring提供的字符编码过滤器
};
}
/**
* 配置文件上传的相关属性,文件上传路径需要在程序中指定服务器的真实路径
* @param registration Servlet动态加载配置
*/
@Override
protected void customizeRegistration(Dynamic registration) {
//设置允许上传的单个文件大小 5M
var singleMax = 5 * 1024 * 1024;
//设置允许上传的总文件大小 20M
var totalMax = 20 * 1024 * 1024;
registration.setMultipartConfig(
new MultipartConfigElement(null,singleMax,totalMax,0));
}
}
如果采用xml配置,如下:Xml代码
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<multipart-config>
<location>/</location>
<max-file-size>10485760</max-file-size>
<max-request-size>5242880</max-request-size>
<file-size-threshold>0</file-size-threshold>
</multipart-config>
</servlet>
location | 上传文件所存放的临时目录。必须指定 |
max-file-size | 文件的最大大小,单位为字节。默认没有限制 |
max-request-size | 请求的最大大小,单位为字节。默认没有限制 |
file-size-threshold | 文件大小阈值,当大于这个阈值时将写入到磁盘,否则在内存中。默认值为0 |
提交上传文件表单
一般而言,文件提交会以POST请求为主,要把enctype定义为"multipart/form-data",否则会解析失败
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>添加图书</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/control/book/save" method="post" enctype="multipart/form-data">
图书封面:<input type="file" name="faceImage" onchange="showImage(this)"/><br/>
<input type="submit" value="提交" />
</form>
</body>
</html>
为此开发一个Controller,用于处理各种文件
@Controller
@RequestMapping("control/book")
public class BookController {
@Autowired private BookService service;
/**
* 上传文件
* @param faceImage 请求上传的文件spring MVC通过MultipartFile进行封装获取
*/
@RequestMapping("/save")
public String save(MultipartFile faceImage) throws IllegalStateException, IOException {
//获取绑定在当前线程上的请求对象
var request =( (ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
//将上传的文件上传至服务器中真实路径
var realpath = request.getServletContext().getRealPath("/images");
//如果文件目录不存在就创建
var dirFile = new File(realpath);
if(!dirFile.exists())dirFile.mkdirs();
//获取上传的文件名
var filename = faceImage.getOriginalFilename();
//目标文件
var dest = new File(dirFile,filename);
//保存文件
faceImage.transferTo(dest);
return "file_list";
}
}
使用CommonsMultipartResolver进行文件上传
步骤一致,代码也一致,看看配置,该上传需要依赖第三方jar包,所以先添加依赖
compile group: 'commons-fileupload', name: 'commons-fileupload', version: '1.4'
配置:
@Bean(name = "multipartResolver")
public MultipartResolver multipartResolver() {
// 设置允许上传的单个文件大小 5M
var singleMax = 5 * 1024 * 1024;
// 设置允许上传的总文件大小 20M
var totalMax = 20 * 1024 * 1024;
var filepath = "/";//文件上传路径,一般在程序中指定为服务器的真实路径
var multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSizePerFile(singleMax);
multipartResolver.setMaxUploadSize(totalMax);
try {
multipartResolver.setUploadTempDir(new FileSystemResource(filepath));
} catch (IOException e) {
e.printStackTrace();
}
return multipartResolver;
}
其它处理方式一致,下面介绍xml方式配置multipartResolver
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 最大允许上传大小5MB -->
<property name="maxUploadSize" value="5242880" />
<property name="maxInMemorySize" value="4096" />
<property name="defaultEncoding" value="UTF-8"></property>
</bean>