Spring MVC 多文件上传大小限制及异常处理
(包括 MaxUploadSizeExceededException 异常)
太阳火神的美丽人生 (http://blog.csdn.net/opengl_es)
本文遵循“署名-非商业用途-保持一致”创作公用协议
补充如下:
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-multipart
官方文档中关于 multipart 上传文件的相关链接。
------------------------
在 spring mvc 的默认配置文件 WEB-INF/xxx-servlet.xml 中加入如下 bean 配置,
<bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding">
<value>UTF-8</value>
</property>
<property name="maxUploadSize">
<!-- 上传文件大小限制为31M,31*1024*1024 -->
<value>32505856</value>
</property>
<property name="maxInMemorySize">
<value>4096</value>
</property>
</bean>
那么当在 html 页面 form 中使用 martpart 的 文件上传组件 <input type="file" name="xxx"/>上传文件到 spring mvc 时,
如果某一个文件超出大小,则会抛出异常,使整个 WEB 应用崩溃,
如何能在自定义的控制器中捕获这一 spring mvc 框架级的异常呢?
我们还是看一下官方文档是怎么说的吧!
Spring HandlerExceptionResolver 接口的实现会处理控制器执行过程中发生的未捕获异常。HandlerExceptionResolver 稍许重组了你在 web 应用描述文件 web.xml 中定义的异常映射。然而,它们提供了更灵活的方式来做到这一点。例如,你来提供异常抛出来哪一个处理器被执行的相关信息。更进一步,编程方式处理异常给你更多的选择性以便在请求转向另一 URL 之前合理做出响应。(和你使用 Servlet 专有异常映射时一样的最终结果)
除了实现 HandlerExceptionResolver 接口外,唯一需要做的事情就是实现 resolveException(Exception, Handler) 方法并返回一个 ModelAndView,你也可以使用预先提供的 SimpleMappingExceptionResolver 或创建一个 @ExceptionHandler 方法。
下面贴出整个控制器的内容,
后三个方法分别是上传多文件处理、处理后结果呈现、还有文件大小超限异常处理。
第一个是通过 jsp 模板呈现页面并替换变量,这个其实很简单,可是好多方法处理后,都无法替换变量,包括重布署,清除重编译等等,甚至重建工程。
后来发现,好多问题并不是问题本身,而是该死的 Maven ,在配置了国内 Maven 镜像并购买的*配上后,才算消停。
总结来说,Maven 的思路是好的,但在国内并不适用,因为我们不是随处都有 WIFI 可用,即使有网速度也很调皮,即使速度还可以,没有*也是狒狒一个!
解决办法,一是在有好网的环境下,用 Maven 把包自动下下来就够了,剩下去除 Maven。
二是搭建本机的 Maven 镜像服务器,这个不仅可以用于 JavaWeb ,而且 Android Studio 的 Gradle 也可以用,有时间偿试一下,后文再补。
说到 Maven 不得不插一句苹果的 CocoaPods,这类东西,在国内 WIFI 没有随处可用的情况下,还是尽量别碰为好,可能苹果的会好些吧!
想来,也许本地 Maven 或 CocoaPods 镜像服务器应该作为各自开发环境的标准才好,在有网的环境下一次性下载到本地或更新,其它任何时侯都不用关心这些问题了。
第二个和第三个是 JSON 输出,没有使用 Spring MVC 自带的方式,配置上就会死循环,不知哪里问题,而 4.2 的方式看官方文档有些麻烦,注解用多了,整个应用都细碎了。
这里使用 fastjson 直接把列表或对象转换成 String 再输出,其实如果想简化的话,也可以自已构建一层父类,来对返回的对象或列表进行处理。
@Controller@RequestMapping("/test")public class TestController implements HandlerExceptionResolver {@RequestMapping("/welcome")public ModelAndView helloWorld() { String message = "<br><div style='text-align:center;'>"+ "<h3>********** Hello World, Spring MVC Tutorial</h3>This message is coming from CrunchifyHelloWorld.java **********</div><br><br>";return new ModelAndView("welcome", "message", message);}@RequestMapping("/say")@ResponseBody public String say() { List<User> userList = new ArrayList<>();User user01 = new User("aaa", "123");User user02 = new User("bbb", "567");User user03 = new User("ccc", "789");userList.add(user01);userList.add(user02);userList.add(user03);String result = JSON.toJSONString(userList, true); return result; } @RequestMapping(path = "/user", method = RequestMethod.GET)@ResponseBody public String getUser() {User user01 = new User("aaa", "123");String result = JSON.toJSONString(user01, true); return result; } @RequestMapping(value = "/upload", method = RequestMethod.GET) public String crunchifyDisplayForm() { return "uploadfile"; } @RequestMapping(value = "/savefiles", method = RequestMethod.POST) public String crunchifySave( @ModelAttribute("uploadForm") FileUploadModel uploadForm, Model map) throws IllegalStateException, IOException { String saveDirectory = "D:/TestResult/crunchify/"; //String saveDirectory = "/root/workspace/upload/"; List<MultipartFile> crunchifyFiles = uploadForm.getFiles(); List<String> fileNames = new ArrayList<String>(); if (null != crunchifyFiles && crunchifyFiles.size() > 0) { for (MultipartFile multipartFile : crunchifyFiles) { String fileName = multipartFile.getOriginalFilename(); if (!"".equalsIgnoreCase(fileName)) { // Handle file content - multipartFile.getInputStream() multipartFile.transferTo(new File(saveDirectory + fileName)); fileNames.add(fileName); } } } map.addAttribute("files", fileNames); return "uploadfilesuccess"; }@Overridepublic ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) {Map<String, Object> model = new HashMap<String, Object>(); if (exception instanceof MaxUploadSizeExceededException) { model.put("errors", exception.getMessage()); } else { model.put("errors", "Unexpected error: " + exception.getMessage()); } model.put("uploadedFile", new FileUploadModel()); return new ModelAndView("/uploadfile", model);}}