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
在有效负载显示存在时说我没有提供?
更新
我已经在内部RequestParamMethodArgumentResolver.java
(内部Spring类)中放置了断点,并且可以看到getParts()
该HttpServletRequest
对象上
根本不 返回 任何
部分。我不确定为什么会这样,但这似乎是问题的根源。从浏览器中,我可以看到正在发出请求,但是无论出于何种原因,多部分数据都无法实现。
问题答案:
我能够弄清楚这一点。要启用对多部分文件的支持,您必须以某种方式进行配置。令人沮丧的文档很难找到,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)
);
}