【问题标题】:Spring Controller @RequestBody with file upload is it possible?Spring Controller @RequestBody 可以上传文件吗?
【发布时间】:2014-06-25 08:21:58
【问题描述】:

我有一个这样的控制器,我想提交一个带有文件上传的表单以及一些表单数据,如标签,如下所示。另外,我想使用@RequestBody 来做到这一点,这样我就可以在包装器上使用@Valid 注释,因为将添加更多变量。

public @ResponseBody WebResponse<Boolean> updateEUSettings(
    final Locale locale,
    @Validated @ModelAttribute final EUPSettingsWrapper endUserPortalSettingsWrapper) {
}

我的包装是:

public class EUPSettingsWrapper {

    private String label;
    private MultipartFile logo;
// getter , setters..etc...
}

但我想将它从 ModelAttributes 转换为 @RequestBody。

我正在尝试的方法是将文件上传分隔为请求参数,如下所示:

public @ResponseBody WebResponse<Boolean> updateEUSettings(
    final Locale locale,
    @Validated @RequestBody final EUPSettingsWrapper endUserPortalSettingsWrapper, 
    @RequestParam(value = "file1", required = true) final MultipartFile logo) {

    endUserPortalSettingsWrapper.setLogo(logo);

    // ...
}

在我的模拟 MVC 中,我正在设置:

getMockMvc().perform(fileUpload(uri).file(logo)
                        .accept(MediaType.APPLICATION_JSON)
                        .content(JSONUtils.toJSON(wrapper))
                        .contentType(MediaType.MULTIPART_FORM_DATA))
                        .andExpect(status().isOk());

但我收到这样的错误:

org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data' not supported

有没有人知道如何将分段文件上传与@RequestBody 一起使用?上面有什么我做错了吗?

【问题讨论】:

标签: spring spring-mvc multipart multipartform-data


【解决方案1】:

您实际上可以在这里简化您的生活,因为您所做的只是提交一个包含一些字段和文件的表单。 您需要 @RequestBody 来完成您正在尝试做的事情。您可以使用常规 Spring MVC 功能,因此您的控制器方法如下所示:

@ResponseBody
public WebResponse<Boolean> updateEUSettings(
     Locale locale, 
     @Valid EUPSettingsWrapper endUserPortalSettingsWrapper, 
     @RequestParam(value = "file1", required = true) MultipartFile logo
) {


}

向此控制器提交请求的客户端需要有一个带有enctype="multipart/form-data" 的表单。

在您的 Spring MVC 测试中,您将编写如下内容:

getMockMvc().perform(fileUpload(uri).file("file1", "some-content".getBytes()) 
                        .param("someEuSettingsProperty", "someValue")
                        .param("someOtherEuSettingsProperty", "someOtherValue")
                        .accept(MediaType.APPLICATION_JSON)
                        .contentType(MediaType.MULTIPART_FORM_DATA))
                        .andExpect(status().isOk());

【讨论】:

  • 非常有趣,但是数据在 Ajax POST 请求中的外观如何?您是否创建了一个表示 EUPSettingsWrapper 的 Object 和一个表示 MultipartFile 的 FormData ,然后将 FormData 分配给 obj.logo ?你也 JSON.stringify() 那个 obj 吗?
  • 不幸的是我不记得了,因为答案很老了:)
  • 另一种方法是将文件字节编码为base64,然后生成的字符串可以在请求json中使用,一般不推荐使用这种模式,但对于特殊情况:{"name":"aa","logo ":encodeBase64(fileByteArray)} 用于编码遵循给定的 url:stackoverflow.com/questions/22172604/…
【解决方案2】:

请在您的 spring-servlet.xml 中添加以下 bean 以添加对多部分请求的支持。

<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

另外不要忘记添加 commons-fileupload jar 的依赖项

【讨论】:

【解决方案3】:

我找不到使用@RequestBody 的方法。

但是,您可以这样做:

@RequestMapping(value = "/uploadStuff", method = RequestMethod.POST)
public MyViewDto doStuff(@RequestPart("json") @Valid MyDto dto,
                         @RequestPart("file") MultipartFile file) { ... }

你可以这样测试:

MockMultipartFile jsonFile = new MockMultipartFile("json", "",
            "application/json", "{}".getBytes());
MockMultipartFile dataFile = new MockMultipartFile("file", "foo.zip", "application/octet-stream", bytes);

mockMvc.perform(fileUpload("/uploadStuff")
            .file(dataFile)
            .file(jsonFile))
            .andExpect(status().isOk());

【讨论】:

  • org.springframework.web.HttpMediaTypeNotSupportedException: 不支持内容类型'application/octet-stream'
【解决方案4】:

我对此有点挣扎,最终将其作为简单参数传递。如果您的请求中没有很多要传递的内容,那很好:

myMethod(@RequestParam("file") MultipartFile myFile,
        @RequestParam("param1") Float param1, @RequestParam("param2") String param2 {}

【讨论】:

    【解决方案5】:

    对于 Spring 4 及更高版本,您可以执行以下操作来获取完整对象:

    public ResponseEntity<Object> upload(@Payload EUPSettingsWrapper wrapper) {
    
    }
    

    注意:没有标签也应该可以工作

    public ResponseEntity<Object> upload(EUPSettingsWrapper wrapper) {
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-14
      • 1970-01-01
      • 1970-01-01
      • 2011-10-25
      • 2012-06-03
      • 2015-08-18
      • 2018-05-12
      相关资源
      最近更新 更多