SpringMVC 之`Multipart`

183 阅读1分钟

最近在浏览spring官网时,发现了这个没怎么用过的方式处理Multipart,提交内容可以包含json文件,SpringMVC 提供的@RequestPart能够同时处理这两者,请求可以从 RESTful 服务场景中的非浏览器客户端提交。

以下示例显示了一个带有 JSON 的文件

POST /someUrl
Content-Type: multipart/mixed

--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp
Content-Disposition: form-data; name="meta-data"
Content-Type: application/json; charset=UTF-8
Content-Transfer-Encoding: 8bit

{
    "name": "value",
    "type": "1"
}
--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp
Content-Disposition: form-data; name="file-data"; filename="file.properties"
Content-Type: text/xml
Content-Transfer-Encoding: 8bit
... File Data ...

以上可以使用 @RequestParamString形式访问“元数据”部分,但你可能希望它从 JSON中 反序列化(类似于 @RequestBody)。使用 HttpMessageConverter 转换多部分后,使用 @RequestPart 注释访问多部分

例如:

public class MetaData {
    private String name;
    private int type;
}
@PostMapping("/")
public String handle(@RequestPart("meta-data") MetaData metadata, @RequestPart("file-data") MultipartFile file) {
// ... 
}

这样可以即处理文件也可以以json形式处理数据,这种方式在android开发请求数据挺方便的,这样就不用以form-data行式提交数据

例子:


import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.IOException;

public class TestMultiPartUpload {

    public static void main(String[] args) throws IOException {
        try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {

            HttpPost post = new HttpPost("http://127.0.0.1:8080/upload");

            post.setHeader("charset", "utf-8");
            post.setHeader("Accept", "application/json");
            post.setHeader("Content-Type", "multipart/mixed;boundary=----QWERTYUIOASDDF");
            FileBody img1 = new FileBody(new File("/Users/apple/Downloads/work/img/xjpic.jpeg"), ContentType.create("image/jpeg"), "1.jpg");

            StringBody meta = new StringBody("{ "name":"v1", "type":1   }", ContentType.APPLICATION_JSON);

            HttpEntity reqEntity = MultipartEntityBuilder.create()
                    .addPart("file-data", img1)
                    .addPart("meta-data", meta)
                    .setBoundary("----QWERTYUIOASDDF")
                    .build();

            post.setEntity(reqEntity);

            try (CloseableHttpResponse response = httpClient.execute(post)) {
                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    System.out.println("Response content: " + new String(resEntity.getContent().readAllBytes()));
                    System.out.println("Response content length: " + resEntity.getContentLength());
                }
                EntityUtils.consume(resEntity);
            }
        }
    }
}

参考1