Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apache Http Client 4 Form Post Multi-part data

I need to post some form parameters to a server through an HTTP request (one of which is a file). So I use Apache HTTP Client like so...

HttpPost httpPost = new HttpPost(urlStr);

params = []
params.add(new BasicNameValuePair("username", "bond"));
params.add(new BasicNameValuePair("password", "vesper"));
params.add(new BasicNameValuePair("file", payload));

httpPost.setEntity(new UrlEncodedFormEntity(params));
httpPost.setHeader("Content-type", "multipart/form-data");

CloseableHttpResponse response = httpclient.execute(httpPost);

The server returns an error, stack trace is..

the request was rejected because no multipart boundary was found
at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:954)
at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:331)
at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:351)
at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:126)
at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:156)

I understand from other posts that I need to somehow come up with a boundary, which is a string not found in the content. But how do I create this boundary in the code I have above? Should it be another parameter? Just a code sample is what I need.

like image 702
AbuMariam Avatar asked Mar 30 '16 19:03

AbuMariam


People also ask

How do you send a multipart file in request body?

To pass the Json and Multipart in the POST method we need to mention our content type in the consume part. And we need to pass the given parameter as User and Multipart file. Here, make sure we can pass only String + file not POJO + file. Then convert the String to Json using ObjectMapper in Service layer.

How do you use multipart form data?

Multipart form data: The ENCTYPE attribute of <form> tag specifies the method of encoding for the form data. It is one of the two ways of encoding the HTML form. It is specifically used when file uploading is required in HTML form. It sends the form data to server in multiple parts because of large size of file.

What is multipart form data in HTTP?

Multipart/form-data is a special type of body that each value is sent as a block of data. Each part is separated by the defined delimiter (a.k.a boundary). The key value is described in the Content-Disposition header of each part. By using multipart/form-data, you can: Send a file or multiple files to your server.


2 Answers

As the exception says, you have not specified the "multipart boundary". This is a string that acts as a separator between the different parts in the request. But in you case it seems like you do not handle any different parts.

What you probably want to use is MultipartEntityBuilder so you don't have to worry about how it all works under the hood.

It should be Ok to do the following

        HttpPost httpPost = new HttpPost(urlStr);

        File payload = new File("/Users/CasinoRoyaleBank");

        HttpEntity entity = MultipartEntityBuilder.create()
                .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
                .addBinaryBody("file", payload)
                .addTextBody("username", "bond")
                .addTextBody("password", "vesper")
                .build();
        httpPost.setEntity(entity);

However, here is a version that should be compatible with @AbuMariam findings below but without the use of deprecated methods/constructors.

        File payload = new File("/Users/CasinoRoyaleBank");

        ContentType plainAsciiContentType = ContentType.create("text/plain", Consts.ASCII);
        HttpEntity entity = MultipartEntityBuilder.create()
                .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
                .addPart("file", new FileBody(payload))
                .addPart("username", new StringBody("bond", plainAsciiContentType))
                .addPart("password", new StringBody("vesper", plainAsciiContentType))
                .build();
        httpPost.setEntity(entity);

        CloseableHttpResponse response = httpclient.execute(httpPost);

The UrlEncodedFormEntity is normally not used for multipart, and it defaults to content-type application/x-www-form-urlencoded

like image 137
gustf Avatar answered Sep 27 '22 23:09

gustf


I accepted gustf's answer because it got rid of the exception I was having and so I thought I was on the right track, but it was not complete. The below is what I did to finally get it to work...

File payload = new File("/Users/CasinoRoyaleBank")
MultipartEntity entity = new MultipartEntity( HttpMultipartMode.BROWSER_COMPATIBLE );
entity.addPart( "file", new FileBody(payload))
entity.addPart( "username", new StringBody("bond"))
entity.addPart( "password", new StringBody("vesper"))
httpPost.setEntity( entity );
CloseableHttpResponse response = httpclient.execute(httpPost);
like image 30
AbuMariam Avatar answered Sep 28 '22 00:09

AbuMariam