Spring MVC:即使存在必需参数,文件上载也会出现错误请求(参数丢失)

我有一个文件上传控制器,其方法如下所示:

@RequestMapping(value = "/upload", method = RequestMethod.POST, produces = {"*/*", "application/json"}) public @ResponseBody ScriptUploadResponse upload(@RequestParam("userId") Long userId, @RequestParam("script") MultipartFile file) { return scriptService.upload(userId, file); } 

这曾经在Spring 3中使用基于XML的配置正常工作。 我最近转移到使用Spring 4的基于Java的配置。当我上传文件时,我得到一个400: Bad request ,抱怨没有提供userId 。 但是当我在浏览器中查看请求时,这就是我所看到的:

 ------WebKitFormBoundaryoJhTJ817NockqUSY Content-Disposition: form-data; name="userId" 1 ------WebKitFormBoundaryoJhTJ817NockqUSY Content-Disposition: form-data; name="script"; filename="script.js" Content-Type: application/javascript ------WebKitFormBoundaryoJhTJ817NockqUSY-- 

spring声称:

HTTP状态400 – 必需长参数’userId’不存在

为什么Spring说当有效负载显示它存在时我没有提供userId

UPDATE

我在RequestParamMethodArgumentResolver.java (一个内部的Spring类)中放置了断点,我可以看到HttpServletRequest对象上的getParts() 根本不返回任何部分。 我不确定为什么会这样,但它似乎是问题的根源。 从浏览器我可以看到正在发出的请求,但无论出于何种原因,多部分数据都无法通过。

我能够弄清楚这一点。 要启用对多部分文件的支持,您必须以某种方式配置事物。 这方面的文档令人沮丧地难以找到,Spring的文档似乎不完整或仅与基于XML的配置相关。 我不确定我是在寻找错误的地方或者是什么,但即使是Google,我也无法找到一个解释如何设置它的地方。 无论如何,这里。

首先必须在Web配置中包含bean。 我只是将以下内容添加到我的配置类(扩展WebMvcConfigurerAdapter ):

 @Bean public MultipartResolver multipartResolver() { return new StandardServletMultipartResolver(); } 

但这还不够。 如果您正在使用Servlet 3.0并且还使用基于Java的配置,则必须配置调度程序servlet以支持多部分文件:

我将以下类添加到我的初始化程序(扩展WebApplicationInitializer ):

 dispatcher.setMultipartConfig( new MultipartConfigElement("/tmp", 25 * 1024 * 1024, 125 * 1024 * 1024, 1 * 1024 * 1024) ); 

整个方法最终看起来像这样:

 @Override public void onStartup(ServletContext servletContext) { AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); rootContext.register(ApplicationConfig.class, WebConfig.class); servletContext.addListener(new ContextLoaderListener(rootContext)); //Spring security servletContext.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain")).addMappingForUrlPatterns(null, false, "/*"); //Enable multipart support ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(rootContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); dispatcher.setMultipartConfig( new MultipartConfigElement("/tmp", 25 * 1024 * 1024, 125 * 1024 * 1024, 1 * 1024 * 1024) ); }