概述
从Spring3.1开始,Spring提供了两个MultipartResolver的实现用于处理multipart请求。
它有两个实现类:
- CommonsMultipartResolver:依赖于Apache下的jakarta Common FileUpload项目解析Multipart请求,可以再SPring的各个版本中使用,只是它要依赖于第三方包才得以实现。
- StandardServletMultipartResolver:是Spring3.1版本后的产物,它依赖于Servlet3.0+的实现,它不用依赖第三方包。
MultipartResolver
在Spring中,既可以通过XML,也可以通过Java去配置MultipartResolver。对于StandardServletMultipartResolver,它的构造方法没有参数,所以很容易对其进行初始化。下面介绍XML的配置方式,在配置DispatcherServlet的地方进行配置。
<servlet>
<servlet-name>dispatcher</servlet-name>x
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
<multipart-config>
<!--临时文件的目录-->
<location>d:/tmp/</location>
<!-- 上传文件最大2M -->
<max-file-size>2097152</max-file-size>
<!-- 上传文件整个请求不超过4M -->
<max-request-size>4194304</max-request-size>
</multipart-config>
</servlet>
要注意xml中web-app节点使用的版本,必须是3.0+。
接下来通过XML或者注解生成一个StandardServletMultipartResolver便可以了。
<bean id="multipartResolver"
class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</bean>
此处的bean的id必须为'multipartResolver',此为Spring的约定,否则可能会导致Controller接受到null。
Controller设置
@Controller
@RequestMapping("/fileupload")
public class FileController {
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public ModelAndView loadMultipartFile(MultipartFile file) {
ModelAndView mv = new ModelAndView();
mv.setView(new MappingJackson2JsonView());
String fileName = file.getOriginalFilename();
file.getContentType();
File dest = new File(fileName);
try {
file.transferTo(dest);
mv.addObject("success", true);
mv.addObject("msg", "上传文件成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
return mv;
}
}
@RequestMapping("/uploadPart", method = RequestMethod.POST)
public ModelAndView uploadPart(Part file) {
ModelAndView mv = new ModelAndView();
mv.setView(new MappingJackson2JsonView());
String fileName = file.getSubmittedFileName();
File dest = new File(fileName);
try {
file.write("d:/tmp/" + fileName);
mv.addObject("success", true);
mv.addObject("msg", "上传文件成功");
} catch (IOException e) {
mv.addObject("success", false);
mv.addObject("msg", "上传文件失败");
e.printStackTrace();
}
return mv;
}
}
两种方法大同小异。
form表单
<form action="/fileupload/uploadPart.do" method="post" enctype="multipart/form-data">
<input type="file" id="file" name="file" value="请选择上传"/>
<input type="submit" value="提交"/>
</form>
借着form表单开始说我遇到的问题。
Controller接收到的参数MultipartFile为null,导致后面抛出空指针异常,百度中的方法都试过,没用。
将表单加入一个input一起提交,Controller却能收到。
最后将表单的提交方法设置成POST,参数正常也实现了保存的功能。
虽然不知道更深层次的原因,但是从中可以看到编码规范的重要性。
然后在注解上限定为post提交
@RequestMapping("/uploadPart", method = RequestMethod.POST)
加上后,如果再犯表单没加method='post',会报405错误,从而快速定位问题。
其他可能会导致为null的原因。
1.form没加enctype="multipart/form-data"
2.bean的id不为multipartResolver