世上最快乐的事,莫过于为理想而奋斗。
1、multipart请求
一般表单提交所形成的请求结果时很简单的,就是以"&"符分割的多个name-value对,如:"firstName=Charles&lastName=Bob"。对于典型的基于文本的表单提交,这种编码形式也足够满足要求,但是对于multipart请求中传送二进制数据,就显得力不从心。
对于multipart请求,对于multipart格式的二进制数据会将一个表单拆分为多个部分(part),每个部分对应一个输入域。在一般的表单输入 域中它所对应的部分中会放置文本型数据,但是如果上传文件的话,它所对应的部分可以是二进制。
2、配置multipart解析器
从 Spring 3.1 开始,Spring 内置了两个 MultipartResolver 类的实现供我们选择:
1) CommonMultipartResolver:使用 Jakarta Commons FileUpload 解析 multipart 请求。
2)StandardServletMultipartResolver:依赖于 Servlet 3.0 对 multipart 请求的支持。
2.1 使用 Servlet 3.0 解析 multipart 请求(配置StandardServletMultipartResolver)
package com.spring.fileupload.config; import javax.servlet.MultipartConfigElement; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration.Dynamic; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.servlet.DispatcherServlet; public class FileUpLoadWebAppInitialzer implements WebApplicationInitializer{ public void onStartup(ServletContext servletContext) throws ServletException { DispatcherServlet ds = new DispatcherServlet(); Dynamic registration = servletContext.addServlet("appServlet", ds); registration.addMapping("/"); registration.setMultipartConfig( new MultipartConfigElement("/temp/uploads")); } }
2)如果我们配置 DispatcherServelt 的 Servlet 初始化类继承了 AbstractAnnotationConfigDispatcherServletInitilaizer 或
AbstractDispatcherServletInitializer 的话,我们可以通过重载 customizeRegistration() 方法来配置 multipart 的具体细节。
package com.spring.fileupload.config; import javax.servlet.MultipartConfigElement; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration.Dynamic; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class FileUpLoadWebAppInitialzer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { // TODO Auto-generated method stub return new Class<?>[] { RootConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { // TODO Auto-generated method stub return new Class<?>[] { WebConfig.class }; } @Override protected String[] getServletMappings() { // TODO Auto-generated method stub return new String[] { "/" }; } @Override protected void customizeRegistration(Dynamic registration) { // TODO Auto-generated method stub new MultipartConfigElement("/temp/uploads"); } }
3)除了指定上传文件的临时目录外,我们还可以通过其他的构造器来配置 multipart 的具体细节,如:
(1) 限定上传文件的最大容量(以字节为单位),默认是没有限制的。
(2)限定整个 multipart 请求的最大容量(以字节为单位),默认是没有限制的。
(3)在上传的过程中,如果文件达到指定大小(以字节为单位),将会写入到临时文件路径中,默认为0。
2.2 配置 Jakarta Commons FileUpload multipart 解析器
package com.spring.fileupload.config; import java.io.IOException; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.FileSystemResource; import org.springframework.web.multipart.MultipartResolver; import org.springframework.web.multipart.commons.CommonsMultipartResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration @EnableWebMvc @ComponentScan("com.spring.fileupload") public class WebConfig extends WebMvcConfigurerAdapter{ @Bean public MultipartResolver multipartResolver() throws IOException { CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(); //设置临时目录路径 multipartResolver.setUploadTempDir(new FileSystemResource("/temp/uploads")); //限定最大的文件容量为2MB multipartResolver.setMaxUploadSize(2097152); //限定最大的内存大小为0字节 multipartResolver.setMaxInMemorySize(0); return multipartResolver; } }
3、处理multipart请求
<!-- enctype属性设置告诉浏览器以multipart数据的形式提交表单 --> <form action="/uploadImg" enctype="multipart/form-data"> <label>Upload Picture</label> <!-- accept属性设置将上传文件类型限制为JPEG,PNG以及GIF图片 --> <input type="file" name="picture" accept="image/jpeg,image/png,image/gif"> </form>
当表单提交时,我们编写的控制器方法就会接受上传的文件数据。
@RequestMapping(value="/uploadImg") public String uploadPicture( @RequestPart("picture") byte[] picture ) { return "success"; }