Thursday, March 29, 2018

Making Http Post request with MultipartForm data

My requirement was to upload a file and pass some JSON in an API in Java. So I googled and found some code as below:

HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(UPLOAD_URI);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.setCharset(Charset.defaultCharset());
String text = "{\"name\":\"manish\",\"occupation\":\"engineer\"}";
builder.addTextBody("info", text);
builder.addPart("doc", new FileBody(file));
httpPost.addHeader("content-type", MediaType.MULTIPART_FORM_DATA);
httpPost .setEntity(builder.build()); httpclient.execute(httpPost);

When I used this code then I got 400 error with reason as "Bad Request" and empty response body. The target server was also in my control and was running Jersey framework on Tomcat. I checked the logs and found just error as 400. Absolutely no message or other info on the reason of the error.
When I ran the API from CURL then it worked with no issues. Thats makes me believe that the issue is in code above.

After a lot of hit and trial I found that the missing piece is the "boundary". Boundary was not added into the "content-type" header. I changed the code above to:

HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(UPLOAD_URI);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.setCharset(Charset.defaultCharset());
String text = "{\"name\":\"maniildersh\",\"occupation\":\"engineer\"}";
builder.setBoundary("------------------------f8ee5b62c27a1db3");
builder.addTextBody("info", text);
builder.addPart("doc", new FileBody(file));
httpPost.addHeader("content-type", MediaType.MULTIPART_FORM_DATA+ "; boundary=------------------------f8ee5b62c27a1db3");
httpPost .setEntity(builder.build()); httpclient.execute(httpPost);

Thats it !  Code started working. Later I changed the boundary to be generated dynamically instead of being static.