I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial – we’ll POST with the HttpClient 4 – using first authorization, then the fluent HttpClient API. Finally – we will discuss how to upload File using HttpClient.

2. Basic POST

First – let’s go over a simple example and send a POST request using HttpClient.

In the following example – we will do a POST with two parameters – “username” and “password“:

@Test
public void whenPostRequestUsingHttpClient_thenCorrect() 
  throws ClientProtocolException, IOException {
    CloseableHttpClient client = HttpClients.createDefault();
    HttpPost httpPost = new HttpPost("http://www.example.com");

    List<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair("username", "John"));
    params.add(new BasicNameValuePair("password", "pass"));
    httpPost.setEntity(new UrlEncodedFormEntity(params));

    CloseableHttpResponse response = client.execute(httpPost);
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
    client.close();
}

Note how we used a List of NameValuePair to include parameters in the POST request.

3. POST with Authorization

Next – let’s see how to do a POST with Authentication credentials using the HttpClient.

In the following example – we send a post request to a URL secured with Basic Authentication:

@Test
public void whenPostRequestWithAuthorizationUsingHttpClient_thenCorrect()
  throws ClientProtocolException, IOException, AuthenticationException {
    CloseableHttpClient client = HttpClients.createDefault();
    HttpPost httpPost = new HttpPost("http://www.example.com");

    httpPost.setEntity(new StringEntity("test post"));
    UsernamePasswordCredentials creds
      = new UsernamePasswordCredentials("John", "pass");
    httpPost.addHeader(new BasicScheme().authenticate(creds, httpPost, null));

    CloseableHttpResponse response = client.execute(httpPost);
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
    client.close();
}

4. POST with JSON

Now – let’s see how to send a POST request with a JSON body using the HttpClient.

In the following example – we’re sending some person information (id, name) as JSON:

@Test
public void whenPostJsonUsingHttpClient_thenCorrect() 
  throws ClientProtocolException, IOException {
    CloseableHttpClient client = HttpClients.createDefault();
    HttpPost httpPost = new HttpPost("http://www.example.com");

    String json = "{"id":1,"name":"John"}";
    StringEntity entity = new StringEntity(json);
    httpPost.setEntity(entity);
    httpPost.setHeader("Accept", "application/json");
    httpPost.setHeader("Content-type", "application/json");

    CloseableHttpResponse response = client.execute(httpPost);
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
    client.close();
}

Note how we’re using the StringEntity to set the body of the request.

We are also setting the ContentType header to application/json to give the server the necessary information about the representation of the content we’re sending.

5. POST with the HttpClient Fluent API

Next – let’s POST with the HttpClient Fluent API; we’re going to send a request with two parameters “username” and “password“:

@Test
public void whenPostFormUsingHttpClientFluentAPI_thenCorrect() 
  throws ClientProtocolException, IOException {
    HttpResponse response = 
      Request.Post("http://www.example.com").bodyForm(
        Form.form().add("username", "John").add("password", "pass").build())
        .execute().returnResponse();

    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}

6. POST Multipart Request

Now – let’s POST a Multipart Request – in the following example, we’ll post a File, username, and password using MultipartEntityBuilder:

@Test
public void whenSendMultipartRequestUsingHttpClient_thenCorrect() 
  throws ClientProtocolException, IOException {
    CloseableHttpClient client = HttpClients.createDefault();
    HttpPost httpPost = new HttpPost("http://www.example.com");

    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.addTextBody("username", "John");
    builder.addTextBody("password", "pass");
    builder.addBinaryBody("file", new File("test.txt"),
      ContentType.APPLICATION_OCTET_STREAM, "file.ext");

    HttpEntity multipart = builder.build();
    httpPost.setEntity(multipart);

    CloseableHttpResponse response = client.execute(httpPost);
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
    client.close();
}

7. Upload a File using HttpClient

Next – let’s see how to upload a File using the HttpClient – we’ll upload the “test.txt” file using MultipartEntityBuilder:

@Test
public void whenUploadFileUsingHttpClient_thenCorrect() 
  throws ClientProtocolException, IOException {
    CloseableHttpClient client = HttpClients.createDefault();
    HttpPost httpPost = new HttpPost("http://www.example.com");

    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.addBinaryBody("file", new File("test.txt"),
      ContentType.APPLICATION_OCTET_STREAM, "file.ext");
    HttpEntity multipart = builder.build();

    httpPost.setEntity(multipart);

    CloseableHttpResponse response = client.execute(httpPost);
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
    client.close();
}

8. Get File Upload Progress

Finally – let’s see how to get the progress of File upload using HttpClient. In the following example – we will extend HttpEntityWrapper to gain visibility into the upload process:

First – here’s the upload method:

@Test
public void whenGetUploadFileProgressUsingHttpClient_thenCorrect()
  throws ClientProtocolException, IOException {
    CloseableHttpClient client = HttpClients.createDefault();
    HttpPost httpPost = new HttpPost("http://www.example.com");

    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.addBinaryBody("file", new File("test.txt"), 
      ContentType.APPLICATION_OCTET_STREAM, "file.ext");
    HttpEntity multipart = builder.build();

    ProgressEntityWrapper.ProgressListener pListener = 
     new ProgressEntityWrapper.ProgressListener() {
        @Override
        public void progress(float percentage) {
            assertFalse(Float.compare(percentage, 100) > 0);
        }
    };

    httpPost.setEntity(new ProgressEntityWrapper(multipart, pListener));

    CloseableHttpResponse response = client.execute(httpPost);
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
    client.close();
}

And here is the interface ProgressListener that enables us to observe the upload progress:

public static interface ProgressListener {
    void progress(float percentage);
}

And here our extended version of HttpEntityWrapper ProgressEntityWrapper“:

public class ProgressEntityWrapper extends HttpEntityWrapper {
    private ProgressListener listener;

    public ProgressEntityWrapper(HttpEntity entity, 
      ProgressListener listener) {
        super(entity);
        this.listener = listener;
    }

    @Override
    public void writeTo(OutputStream outstream) throws IOException {
        super.writeTo(new CountingOutputStream(outstream, 
          listener, getContentLength()));
    }
}

And the extended version of FilterOutputStreamCountingOutputStream“:

public static class CountingOutputStream extends FilterOutputStream {
    private ProgressListener listener;
    private long transferred;
    private long totalBytes;

    public CountingOutputStream(
      OutputStream out, ProgressListener listener, long totalBytes) {
        super(out);
        this.listener = listener;
        transferred = 0;
        this.totalBytes = totalBytes;
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        out.write(b, off, len);
        transferred += len;
        listener.progress(getCurrentProgress());
    }

    @Override
    public void write(int b) throws IOException {
        out.write(b);
        transferred++;
        listener.progress(getCurrentProgress());
    }

    private float getCurrentProgress() {
        return ((float) transferred / totalBytes) * 100;
    }
}

Note that:

  • When extending FilterOutputStream to “CountingOutputStream” – we are overriding the write() method to count the written (transferred) bytes
  • When extending HttpEntityWrapper to “ProgressEntityWrapper” – we are overriding the writeTo() method to use ourCountingOutputStream

9. Conclusion

In this tutorial, we illustrated the most common ways to send POST HTTP Requests with the Apache HttpClient 4.

We learned how to send a POST request with Authorization, how to post using HttpClient fluent API and how to upload a file and track its progress.

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE LESSONS

Sort by:   newest | oldest | most voted
daisy
Guest
Hello, Thank you for such a great tutorial.. When I am using “POST with Authorization”, for one of my code to create remote job in Jenkins, i always get error message : “HTTP/4.1 401 Authorization Required”. I am sure I am able to login into Jenkins and could create job in jenkins. But when I try to create job via Apache HTTP Client, it is failing. Please find my code here : String input = getConfigJobXML(); CloseableHttpClient client = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(postUrl); httpPost.setEntity(new StringEntity(input,ContentType.APPLICATION_ATOM_XML)); UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password); httpPost.addHeader(new BasicScheme().authenticate(creds, httpPost, null)); CloseableHttpResponse response =… Read more »
daisy
Guest

I am using Jenikins via Apache (SSL).

Eugen Paraschiv
Guest

Hey Daisy – that can happen for a variety of reasons – can you please open an issue over on github and provide your sample code as a test that I can run – and I’d be happy to take a look at what that reason is. Cheers,
Eugen.

springusr
Guest

Hi,

Trying to process file with json object as well with something like below but no success:

@RequestMapping(method = RequestMethod.POST)
public ResponseEntity handleFileUpload(@RequestPart MultipartFile file, HttpServletRequest request,@RequestPart User user) {

Basically I want to send json data and file together in same request, not able to figure on how to do mapping and not sure even we can test easily using postman. Advanced rest client allows it though to send mix raw json and file.

Eugen Paraschiv
Guest

That’s interesting, but keep in mind that the client side of things (which is what this article is about) and the server side of things are two completely different things. So – if you’re trying to get a Spring MVC mapping to work, this is probably not the right place to ask 🙂
Feel free to reach out over email with more detail. Cheers,
Eugen.

Sweidán Omár
Guest

Hi Eugen!

What should I add to my gradle file to be able to use CloseableHttpClient?

Grzegorz Piwowarek
Guest

This class comes from HttpClient4 and you can find it here https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
After picking a version, you will be able to pick Maven/Gradle/SBT or many other formats.
In this case, compile group: ‘org.apache.httpcomponents’, name: ‘httpclient’, version: ‘4.5.2’ this should do the trick.

Sweidán Omár
Guest

Thanks. I used the entry you advised, but it produces this warning:

Warning:WARNING: Dependency org.apache.httpcomponents:httpclient:4.5.2 is ignored for debug as it may be conflicting with the internal version provided by Android.

Grzegorz Piwowarek
Guest

I do not really have an experience with Android so can’t tell you more than it’s written there but I guess the point here is to find a version that works with your setup or maybe even utilize the one provided by Android

Sweidán Omár
Guest

Thank you.

Edit: I found the solution here:
http://stackoverflow.com/questions/32153318/httpclient-wont-import-in-android-studio
“HttpClient is not supported any more in sdk 23. You have to use URLConnection…”

Grzegorz Piwowarek
Guest

That’s good to know 🙂 I am glad the problem is solved

Deepak
Guest

I have create a PUT HttpClient .
HttpPut httpPut
= new HttpPut(“url”);
httpPut.addHeader(“Content-Type”, “application/json”);

But not able to pass raw body information.
Please help to pass body information to application.

Eugen Paraschiv
Guest

Hey Deepak,
Have you tried defining a StringEntity and setting that on your request (have a look at section 4)?
Cheers,
Eugen.

Harl
Guest

Hi,

I successfully uploaded a file with the above code but I have a issue with the content of the uploaded file (.txt).
Some info (specified in the MultipartEntityBuilder) have been added to it.

For example, before upload, content of myfile.txt is :

mycontent

After the upload, content of the file is :

–01Uvcza0GVBcH3R6pe2DMJ_GoHpFyEKoIRdqQ
Content-Disposition: form-data; name=”upfile”; filename=”file.ext”
Content-Type: application/octet-stream

mycontent
–01Uvcza0GVBcH3R6pe2DMJ_GoHpFyEKoIRdqQ–

How can I get rid of these info ?

Thanks

wpDiscuz