带有 JSON 的 Spring MVC 多部分请求

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21329426/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 20:12:04  来源:igfitidea点击:

Spring MVC Multipart Request with JSON

jsonspringspring-mvc

提问by Sunil Kumar

I want to post a file with some JSON data using Spring MVC. So I've developed a rest service as

我想使用 Spring MVC 发布一个包含一些 JSON 数据的文件。所以我开发了一个休息服务

@RequestMapping(value = "/servicegenerator/wsdl", method = RequestMethod.POST,consumes = { "multipart/mixed", "multipart/form-data" })
@ResponseBody
public String generateWSDLService(@RequestPart("meta-data") WSDLInfo wsdlInfo,@RequestPart("file") MultipartFile file) throws WSDLException, IOException,
        JAXBException, ParserConfigurationException, SAXException, TransformerException {
    return handleWSDL(wsdlInfo,file);
}

When I send a request from the rest client with content-Type = multipart/form-data or multipart/mixed, I get the next exception: org.springframework.web.multipart.support.MissingServletRequestPartException

当我使用 发送来自其余客户端的请求时 content-Type = multipart/form-data or multipart/mixed,我收到下一个异常: org.springframework.web.multipart.support.MissingServletRequestPartException

Can anyone help me in solving this issue?

谁能帮我解决这个问题?

Can I use @RequestPartto send both Multipart and JSON to a server?

我可以使用@RequestPart将 Multipart 和 JSON 都发送到服务器吗?

回答by Sunil Kumar

This is how I implemented Spring MVC Multipart Request with JSON Data.

这就是我使用 JSON 数据实现 Spring MVC Multipart Request 的方式。

Multipart Request with JSON Data (also called Mixed Multipart):

带有 JSON 数据的多部分请求(也称为混合多部分):

Based on RESTful service in Spring 4.0.2 Release, HTTP request with the first part as XML or JSON formatted data and the second part as a file can be achieved with @RequestPart. Below is the sample implementation.

基于 Spring 4.0.2 Release 中的 RESTful 服务,可以通过 @RequestPart 实现第一部分为 XML 或 JSON 格式数据,第二部分为文件的 HTTP 请求。下面是示例实现。

Java Snippet:

Java代码段:

Rest service in Controller will have mixed @RequestPart and MultipartFile to serve such Multipart + JSON request.

Controller 中的 Rest 服务将混合 @RequestPart 和 MultipartFile 来服务这样的 Multipart + JSON 请求。

@RequestMapping(value = "/executesampleservice", method = RequestMethod.POST,
    consumes = {"multipart/form-data"})
@ResponseBody
public boolean executeSampleService(
        @RequestPart("properties") @Valid ConnectionProperties properties,
        @RequestPart("file") @Valid @NotNull @NotBlank MultipartFile file) {
    return projectService.executeSampleService(properties, file);
}

Front End (JavaScript) Snippet:

前端 (JavaScript) 代码段:

  1. Create a FormData object.

  2. Append the file to the FormData object using one of the below steps.

    1. If the file has been uploaded using an input element of type "file", then append it to the FormData object. formData.append("file", document.forms[formName].file.files[0]);
    2. Directly append the file to the FormData object. formData.append("file", myFile, "myfile.txt");OR formData.append("file", myBob, "myfile.txt");
  3. Create a blob with the stringified JSON data and append it to the FormData object. This causes the Content-type of the second part in the multipart request to be "application/json" instead of the file type.

  4. Send the request to the server.

  5. Request Details:
    Content-Type: undefined. This causes the browser to set the Content-Type to multipart/form-data and fill the boundary correctly. Manually setting Content-Type to multipart/form-data will fail to fill in the boundary parameter of the request.

  1. 创建一个 FormData 对象。

  2. 使用以下步骤之一将文件附加到 FormData 对象。

    1. 如果文件已使用“文件”类型的输入元素上传,则将其附加到 FormData 对象。 formData.append("file", document.forms[formName].file.files[0]);
    2. 直接将文件附加到 FormData 对象。 formData.append("file", myFile, "myfile.txt");或者formData.append("file", myBob, "myfile.txt");
  3. 使用字符串化的 JSON 数据创建一个 blob,并将其附加到 FormData 对象。这会导致多部分请求中第二部分的 Content-type 为“application/json”而不是文件类型。

  4. 将请求发送到服务器。

  5. 请求详细信息:
    Content-Type: undefined。这会导致浏览器将 Content-Type 设置为 multipart/form-data 并正确填充边界。手动将 Content-Type 设置为 multipart/form-data 将无法填写请求的边界参数。

Javascript Code:

Javascript代码:

formData = new FormData();

formData.append("file", document.forms[formName].file.files[0]);
formData.append('properties', new Blob([JSON.stringify({
                "name": "root",
                "password": "root"                    
            })], {
                type: "application/json"
            }));

Request Details:

请求详情:

method: "POST",
headers: {
         "Content-Type": undefined
  },
data: formData

Request Payload:

请求有效载荷:

Accept:application/json, text/plain, */*
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryEBoJzS3HQ4PgE1QB

------WebKitFormBoundaryvijcWI2ZrZQ8xEBN
Content-Disposition: form-data; name="file"; filename="myfile.txt"
Content-Type: application/txt


------WebKitFormBoundaryvijcWI2ZrZQ8xEBN
Content-Disposition: form-data; name="properties"; filename="blob"
Content-Type: application/json


------WebKitFormBoundaryvijcWI2ZrZQ8xEBN--

回答by mohi

This must work!

这必须工作!

client (angular):

客户端(角度):

$scope.saveForm = function () {
      var formData = new FormData();
      var file = $scope.myFile;
      var json = $scope.myJson;
      formData.append("file", file);
      formData.append("ad",JSON.stringify(json));//important: convert to JSON!
      var req = {
        url: '/upload',
        method: 'POST',
        headers: {'Content-Type': undefined},
        data: formData,
        transformRequest: function (data, headersGetterFunction) {
          return data;
        }
      };

Backend-Spring Boot:

后端弹簧启动:

@RequestMapping(value = "/upload", method = RequestMethod.POST)
    public @ResponseBody
    Advertisement storeAd(@RequestPart("ad") String adString, @RequestPart("file") MultipartFile file) throws IOException {

        Advertisement jsonAd = new ObjectMapper().readValue(adString, Advertisement.class);
//do whatever you want with your file and jsonAd

回答by Vaelyr

As documentation says:

正如文档所说:

Raised when the part of a "multipart/form-data" request identified by its name cannot be found.

This may be because the request is not a multipart/form-data either because the part is not present in the request, or because the web application is not configured correctly for processing multipart requests -- e.g. no MultipartResolver.

当无法找到由其名称标识的“multipart/form-data”请求的一部分时引发。

这可能是因为请求不是多部分/表单数据,或者因为该部分不存在于请求中,或者因为 Web 应用程序没有正确配置来处理多部分请求——例如没有 MultipartResolver。