Spring MVC 多文件上传大小限制及异常处理

时间:2022-12-13 17:28:27

Spring MVC  多文件上传大小限制及异常处理

(包括 MaxUploadSizeExceededException 异常)

太阳火神的美丽人生 (http://blog.csdn.net/opengl_es)

本文遵循“署名-非商业用途-保持一致”创作公用协议

转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS、Android、Html5、Arduino、pcDuino否则,出自本博客的文章拒绝转载或再转载,谢谢合作。



补充如下:

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 框架级的异常呢?


我们还是看一下官方文档是怎么说的吧!


http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-exceptionhandlers-resolver

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);}}