Java 9 HttpClient发送multipart/form-data请求

以下是表格:

<form action="/example/html5/demo_form.asp" method="post" 
enctype=”multipart/form-data”>
   <input type="file" name="img" />
   <input type="text" name=username" value="foo"/>
   <input type="submit" />
</form>

何时提交此表单,请求将如下所示:

POST /example/html5/demo_form.asp HTTP/1.1
Host: 10.143.47.59:9093
Connection: keep-alive
Content-Length: 326
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://10.143.47.59:9093
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryEDKBhMZFowP9Leno
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4

Request Payload
------WebKitFormBoundaryEDKBhMZFowP9Leno
Content-Disposition: form-data; name="username"

foo
------WebKitFormBoundaryEDKBhMZFowP9Leno
Content-Disposition: form-data; name="img"; filename="out.txt"
Content-Type: text/plain


------WebKitFormBoundaryEDKBhMZFowP9Leno--

请注意“请求有效负载”,你可以在表单中看到两个参数,用户名和img(form-data; name =“img”; filename =“out.txt”),并且名字是文件系统中的实际文件名(或路径),您将在后端按名称(而不是文件名)接收文件(例如spring controller).
如果我们使用Apache Httpclient来模拟请求,我们将编写这样的代码:

MultipartEntity mutiEntity = newMultipartEntity();
File file = new File("/path/to/your/file");
mutiEntity.addPart("username",new StringBody("foo", Charset.forName("utf-8")));
mutiEntity.addPart("img", newFileBody(file)); //img is name, file is path

但在java 9中,我们可以编写这样的代码:

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.
        newBuilder(new URI("http:///example/html5/demo_form.asp"))
       .method("post",HttpRequest.BodyProcessor.fromString("foo"))
       .method("post", HttpRequest.BodyProcessor.fromFile(Paths.get("/path/to/your/file")))
       .build();
HttpResponse response = client.send(request, HttpResponse.BodyHandler.asString());
System.out.println(response.body());

现在你看,我怎么能设置参数的“名称”?

最佳答案
您可以进行多形式数据通话的方向如下:

BodyProcessor可以与其默认实现一起使用,或者也可以使用自定义实现.几乎没有使用它们的方法是:

>通过字符串读取处理器:

HttpRequest.BodyProcessor dataProcessor = HttpRequest.BodyProcessor.fromString("{\"username\":\"foo\"}")

>使用其路径从文件创建处理器

Path path = Paths.get("/path/to/your/file"); // in your case path to 'img'
HttpRequest.BodyProcessor fileProcessor = HttpRequest.BodyProcessor.fromFile(path);

要么

>您可以使用apache.commons.lang(或您可以提供的自定义方法)将文件输入转换为字节数组,以添加一个小的util,如:

org.apache.commons.fileupload.FileItem file;

org.apache.http.HttpEntity multipartEntity = org.apache.http.entity.mime.MultipartEntityBuilder.create()
       .addPart("username",new StringBody("foo", Charset.forName("utf-8")))
       .addPart("img", newFileBody(file))
       .build();
multipartEntity.writeTo(byteArrayOutputStream);
byte[] bytes = byteArrayOutputStream.toByteArray();

然后byte []可以与BodyProcessor一起使用:

HttpRequest.BodyProcessor byteProcessor = HttpRequest.BodyProcessor.fromByteArray();

此外,您可以创建请求:

HttpRequest request = HttpRequest.newBuilder()
            .uri(new URI("http:///example/html5/demo_form.asp"))
            .headers("Content-Type","multipart/form-data","boundary","boundaryValue") // appropriate boundary values
            .POST(dataProcessor)
            .POST(fileProcessor)
            .POST(byteProcessor) //self-sufficient
            .build();

相同的响应可以作为文件处理,并使用新的HttpClient

HttpResponse.BodyHandler bodyHandler = HttpResponse.BodyHandler.asFile(Paths.get("/path"));

HttpClient client = HttpClient.newBuilder().build();

如:

HttpResponse response = client.send(request, bodyHandler);
System.out.println(response.body());

转载注明原文:Java 9 HttpClient发送multipart/form-data请求 - 代码日志