multipart格式的数据会将一个表单拆分成为多个部分,每个部分对应一个输入域
1. 配置multipart解析器
Spring中通过MultipartResolver
接口的实现类来解析multipart请求中的内容,从Spring3.1开始,Spring内置了两个它的实现类:
CommonsMultipartResolver
:使用Jakarta Comomons FileUpload 解析multipart请求StandardServletMultipartResolver
:依赖于Servlet3.0对multipart请求的支持
1.1 使用StandardServletMultipartResolver
没有构造器参数,也没要设置的属性
@Bean
public MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
这里只是声明了StandardServletMultipartResolver,没有关于上传的任何配置,它的配置不在Spring中配置,而是在Servlet中指定。至少要指定文件上传过程中的写入的临时文件路径,否则无法正常工作。所以我们必须要在web.xml或Servlet初始化类中将multipart的具体细节作为DispatcherServlet配置的一部分
1.1.1 采用servlet初始化类的方式
DispatcherServlet ds = new DispatcherServlet ();
Dynamic registration = context.addServlet("appServlet", ds);
resistration.addMapping("/");
registration.setMultipartConfig(new MultipartConfigElement("/tmp/spitter/uploads"));
1.1.2 采用重载方法方式
如果我们采用的是继承AbstractAnnotationConfigDispatcherServletInitializer
或AbstractDispatcherServletInitializer
的方法注册DispatcherServlet,那么我们就不会直接创建DispatcherServlet的实例并注册到Servlet上下文中,就不会有对Dynamic Servlet registration 的引用提供使用了:
@Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
//设置上传文件的临时存储目录
registration.setMultipartConfig(new MultipartConfigElement("/tmp/spitter/uploads"));
}
- MultipartConfigElement 的构造器参数
- 临时路径
- 上传文件的最大容量(字节),默认没有限制
- 整个multipart请求的最大容量(字节),默认没有限制
- 上传过程中,如果文件大小达到了一个指定的最大容量(字节),将会写入到临时文件路径中,默认值为0,也就是所有上传文件都会写入到磁盘上
new MultipartConfigElement("/tmp/spitter/uploads", 2097152, 4194304, 0)
限制文件大小不超过2MB,整个请求不超过4MB,所有文件写入磁盘中
1.1.3 采用web.xml方式
<servlet> <!--注册DispatcherServlet-->
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<multipart-config>
<location>/tmp/spitter/uploads</location> <!--location必须配置-->
<max-file-size>2097152</max-file-size>
<max-request-size>4194304</max-request-size>
</multipart-config>
</servlet>
1.2 配置Jakarta Comomons FileUpload multipart 解析器
如果应用部署到非Servlet3.0容器中,就需要新的MultipartResolver实现,Spring内置了CommonsMultipartResolver
@Bean
public MultipartResolver multipartResolver() {
return new CommonsMultipartResolver();
}
CommonsMultipartResolver
不强制要求设置临时文件路径,默认是Servlet容器的临时目录
也可以手动设置:
@Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setUploadTempDir(new FileSystemResource("/tmp/spitter/uploads"));
multipartResolver.setMaxUploadSize(2097152);
multipartResolver.setMaxInMemorySize(0);
return new CommonsMultipartResolver();
}
这种方式无法设定multipart请求整体最大容量。
2. 处理multipart请求
2.1 接收MultipartFile
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String register(@RequestPart("image") byte[] image,...) {
...
}
使用byte数组接收上传文件功能有限,Spring提供了MultipartFile接口
public interface MultipartFile {
String getName();
String getOriginalFilename();
String getContentType();
boolean isEmpty();
long getSize();
byte[] getBytes() throws IOException;
InputStream getInputStream() throws IOException;
void transferTo(File var1) throws IOException, IllegalStateException;
}
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String register(@RequestPart("image") MultipartFile image,...) {
...
image.transferTo(new File("E:\\exec\\" + image.getOriginalFilename())); //保存文件
...
}
2.2 1
2.3 以Part形式接收上传文件
如果应用部署到Servlet3.0容器中,SpringMVC也能接受javax.servlet.http.Part作为控制器方法的参数
public interface Part {
InputStream getInputStream() throws IOException;
String getContentType();
String getName();
String getSubmittedFileName();
long getSize();
void write(String var1) throws IOException;
void delete() throws IOException;
String getHeader(String var1);
Collection<String> getHeaders(String var1);
Collection<String> getHeaderNames();
}
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String register(@RequestPart("image") Part image,...) {
...
image.write("E:\\exec\\" + image.getSubmittedFileName());
...
}
接口方法基本相同
javax.servlet-api 的版本要在3.1以下的版本中没有getSubmittedFileName()
方法,要注意可能项目引入的包是3.1以上的,但运行的容器中版本是3.1以下的,会报错NoSuchMethodError
如果以Part参数的形式接收文件上传,就没有必要配置MultipartResolver
bean了,只有使用MultipartFile
的时候才需要配置MultipartResolver
之前设置的new MultipartConfigElement("/tmp/spitter/uploads", 2097152, 4194304, 0)
上传文件配置和这个MultipartResolver
没关系,是所有上传文件的规范
212 ↩︎