Below is a form:
enctype=”multipart/form-data”>
when will submit this form, the request will look like this:
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--
please pay attention to the "Request Payload", you can see the two params in the form, the username and the img(form-data; name="img"; filename="out.txt"), and the finename is the real file name(or path) in your filesystem, you will receive the file by name(not filename) in your backend(such as spring controller).
if we use Apache Httpclient to simulate the request, we will write such code:
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
But in java 9, We could write such code:
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());
Now you see, how could I set the "name" of the param?
解决方案
A direction in which you can attain making a multiform-data call could be as follows:
BodyProcessor can be used with their default implementations or else a custom implementation can also be used. Few of the ways to use them are :
Read the processor via a string as :
HttpRequest.BodyProcessor dataProcessor = HttpRequest.BodyProcessor.fromString("{\"username\":\"foo\"}")
Creating a processor from a file using its path
Path path = Paths.get("/path/to/your/file"); // in your case path to 'img'
HttpRequest.BodyProcessor fileProcessor = HttpRequest.BodyProcessor.fromFile(path);
OR
You can convert the file input to a byte array using the apache.commons.lang(or a custom method you can come up with) to add a small util like :
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();
and then the byte[] can be used with BodyProcessor as:
HttpRequest.BodyProcessor byteProcessor = HttpRequest.BodyProcessor.fromByteArray();
Further, you can create the request as :
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();
The response for the same can be handled as a file and with a new HttpClient using
HttpResponse.BodyHandler bodyHandler = HttpResponse.BodyHandler.asFile(Paths.get("/path"));
HttpClient client = HttpClient.newBuilder().build();
as:
HttpResponse response = client.send(request, bodyHandler);
System.out.println(response.body());