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

时间:2014-08-03 23:08:27

标签: java spring 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'不存在

为什么春天说当有效载荷显示它存在时我还没有提供userId

更新

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

1 个答案:

答案 0 :(得分:2)

我能够弄清楚这一点。要启用对多部分文件的支持,您必须以某种方式配置事物。这方面的文档令人沮丧地难以找到,而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)
    );
}