6

I am using Apache HttpComponents v4.3.3 (maven httpclient and httpmime). I need to upload a file with some metadata. The curl command, which works, looks like the following.

curl -k -i -H "Content-Type: multipart/mixed" -X POST --form 'field1=val1' --form 'field2=val2' --form '[email protected];type=application/zip' https://www.some.domain/

I have tried mimicking this curl post as the following.

HttpEntity entity = MultiPartEntityBuilder
 .create()
 .addPart("field1",new StringBody("val1",ContentType.TEXT_PLAIN))
 .addPart("field2",new StringBody("val2",ContentType.TEXT_PLAIN))
 .addPart("file", new FileBody(new File("somefile.zip"), ContentType.create("application/zip"))
 .build();
HttpPost post = new HttpPost("https://www.some.domain");
post.addHeader("Content-Type", "multipart/mixed");

However, after I use HttpClient to execute the HttpPost, I get the following exception (server code is also Java running on Jetty).

org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found

When I add a trace to curl

curl --trace - -k -i -H "Content-Type: multipart/mixed" -X POST --form 'field1=val1' --form 'field2=val2' --form '[email protected];type=application/zip' https://www.some.domain/

I see that the form field/value pairs are set as HTTP headers.

Content-Disposition: form-data; name=field1...value1

Any idea on what I'm doing wrong here? Any help is appreciated.

2 Answers 2

7

I tinkered a bit and did two things to get the code working.

  • no longer use addPart(...)
  • no longer set Content-Type header

Here's the revised snippet that's working in case anyone is interested.

HttpEntity entity = MultipartEntityBuilder
 .create()
 .addTextBody("field1","val1")
 .addTextBody("field2","val2")
 .addBinaryBody("file", new File("somefile.zip"),ContentType.create("application/zip"),"somefile.zip")
 .build();
HttpPost post = new HttpPost("https://www.some.domain");
post.setEntity(entity);

I also set HttpComponents to debug mode.

-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
-Dorg.apache.commons.logging.simplelog.showdatetime=true
-Dorg.apache.commons.logging.simplelog.log.org.apache.http=DEBUG

It turns out that each part now has a boundary. Even better yet, the Content-Type and boundary are autogenerated.

Content-Type: multipart/form-data; boundary=5ejxpaJqXwk2n_3IVZagQ1U0_J_X9MdGvst9n2Tc

Sign up to request clarification or add additional context in comments.

2 Comments

Don't know why you didn't get any votes - this is THE solution for multipart on Android! Other stuff I found did it all manually which is quite cumbersome....
But this is not multipart/mixed. There seem to be hundreds of answers how to do it with multipart/form-data.
1

Here my full code based in last response, but is slightly different, i had the same error but now works (thanks Jane!):

public String sendMyFile(String p_file, String p_dni, String p_born_date) throws Exception {

    HttpClient httpclient = HttpClientBuilder.create().build();

    HttpPost    httppost = new HttpPost("http://localhost:2389/TESTME_WITH_NETCAT");

    /* Campos del formulario del POST que queremos hacer */
    File        fileIN  = new File(p_file);

    /* Construimos la llamada */
    MultipartEntityBuilder reqEntity = MultipartEntityBuilder.create();

    reqEntity
            .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
            .addBinaryBody  ("p_file"               , fileIN)
            .addTextBody    ("p_dni"                , p_dni)
            .addTextBody    ("p_born_date"  , p_born_date);

    httppost.setEntity(reqEntity.build());

    System.out.println("executing request " + httppost.getRequestLine());

    HttpResponse response = httpclient.execute(httppost);

    System.out.println("1 ----------------------------------------");
    System.out.println(response.getStatusLine());
    System.out.println("2 ----------------------------------------");
    System.out.println(EntityUtils.toString(response.getEntity()));
    System.out.println("3 ----------------------------------------");

    HttpEntity resEntity = response.getEntity();

    if (resEntity != null) {
        System.out.println("Response content length: " + resEntity.getContentLength());
    }

    return "OK";
}

1 Comment

Welcome to Stack Overflow! While this code snippet may solve the question, including an explination really helps to improve the quality of your post. Remember that you are answering the questions for readers in the future, and those people might not know the reasons for your code suggestion.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.