HttpClient系列-Post使用基礎(chǔ)知識(shí)(三)

簡(jiǎn)述

本文學(xué)習(xí)如何簡(jiǎn)單的使用POST,如何上傳文件等等場(chǎng)景

基礎(chǔ)POST

首先,讓我們來看一個(gè)簡(jiǎn)單的例子,并使用HttpClient發(fā)送POST請(qǐng)求。

我們將使用兩個(gè)參數(shù) - “username”和“password” 進(jìn)行POST :

@Test
public void test() 
  throws ClientProtocolException, IOException {
    CloseableHttpClient client = HttpClients.createDefault();

    List<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair("username", "John"));
    params.add(new BasicNameValuePair("password", "pass"));
    httpPost.setEntity(new UrlEncodedFormEntity(params));
 
    HttpPost httpPost = new HttpPost("http://localhost:8080");

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

請(qǐng)注意我們?nèi)绾问褂肔ist<NameValuePair>在POST請(qǐng)求中包含參數(shù)。

使用授權(quán)進(jìn)行POST

接下來,讓我們看看如何使用HttpClient對(duì)身份驗(yàn)證憑據(jù)進(jìn)行POST 。

在以下示例中 - 我們通過添加Authorization在Header向使用基本身份驗(yàn)證保護(hù)的URL發(fā)送POST請(qǐng)求:

@Test
public void test()
  throws ClientProtocolException, IOException, AuthenticationException {
    CloseableHttpClient client = HttpClients.createDefault();

    HttpPost httpPost = new HttpPost("http://localhost:8080");


   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();
}

使用JSON POST

現(xiàn)在 - 讓我們看看如何使用HttpClient向JSON主體發(fā)送POST請(qǐng)求。

在以下示例中 - 我們將一些Person(id,name)作為JSON發(fā)送:

@Test
public void test() 
  throws ClientProtocolException, IOException {
    CloseableHttpClient client = HttpClients.createDefault();

    HttpPost httpPost = new HttpPost("http://localhost:8080");

    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();
}

注意我們?nèi)绾问褂?code>StringEntity來設(shè)置請(qǐng)求的主體。

我們還將ContentType標(biāo)頭設(shè)置為application / json ,以便為服務(wù)器提供有關(guān)我們發(fā)送的內(nèi)容表示的必要信息。

使用HttpClient Form進(jìn)行 POST

接下來,讓我們使用HttpClient Fluent API進(jìn)行POST 。

我們將發(fā)送一個(gè)帶有兩個(gè)參數(shù)“ username ”和“ password ” 的請(qǐng)求:

@Test
public void test() 
  throws ClientProtocolException, IOException {
    HttpResponse response = Request.Post("http://localhost:8080").bodyForm(
      Form.form().add("username", "John").add("password", "pass").build())
      .execute().returnResponse();
 
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}

POST多參數(shù)請(qǐng)求

現(xiàn)在,讓我們發(fā)一個(gè)多參數(shù)請(qǐng)求。

我們將使用MultipartEntityBuilder發(fā)布文件,useranme和password:

@Test
public void whenSendMultipartRequestUsingHttpClient_thenCorrect() 
  throws ClientProtocolException, IOException {
    CloseableHttpClient client = HttpClients.createDefault();

    HttpPost httpPost = new HttpPost("http://localhost:8080");

    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();
}

使用HttpClient上傳文件

接下來,讓我們看看如何使用HttpClient上傳文件。

我們將使用MultipartEntityBuilder上傳“ test.txt ”文件:

@Test
public void test() throws ClientProtocolException, IOException {
    CloseableHttpClient client = HttpClients.createDefault();

    HttpPost httpPost = new HttpPost("http://localhost:8080");

    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();
}

獲取文件上傳 進(jìn)度

最后 - 讓我們看看如何使用HttpClient獲取文件上傳的進(jìn)度。

在下面的示例中,我們將擴(kuò)展HttpEntityWrapper以獲得對(duì)上載過程的可見性。

首先 - 這是上傳方法:

@Test
public void test()
  throws ClientProtocolException, IOException {
    CloseableHttpClient client = HttpClients.createDefault();

    HttpPost httpPost = new HttpPost("http://localhost:8080");

    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.addBinaryBody("file", new File("test.txt"), ContentType.APPLICATION_OCTET_STREAM, "file.ext");
    HttpEntity multipart = builder.build();
 
    ProgressEntityWrapper.ProgressListener pListener = 
      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();
}

我們還將添加接口ProgressListener,使我們能夠觀察上傳進(jìn)度:

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

這是我們的擴(kuò)展版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()));
    }
}

而FilterOutputStream的擴(kuò)展版CountingOutputStream

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;
    }
}

注意:

  • 將FilterOutputStream擴(kuò)展為CountingOutputStream時(shí) -我們重寫write()方法來計(jì)算寫入(傳輸)的字節(jié)數(shù)
  • 將HttpEntityWrapper擴(kuò)展為ProgressEntityWrapper時(shí) -我們重寫writeTo()方法以使用我們的CountingOutputStream

小結(jié)

HttpClient的基礎(chǔ)知識(shí)到本文就已經(jīng)介紹結(jié)束,希望對(duì)你有所收獲。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容