您的位置:

使用HttpClient下载

一、HttpClient简介

HttpClient是一个Apache软件基金会下的开源Java HTTP客户端库,支持最新的HTTP/1.1协议规范。HttpClient以URL方式连向服务器并获取数据,因此HttpClient在处理HTTP与HTTPS协议方面表现出色。

使用HttpClient可以轻松地进行HTTP请求。相比于JSoup,HttpClient提供了更多的配置参数、更加丰富的Header设置和HTTP认证等功能,是一个更完善的方案。

在Android开发中,我们经常使用HttpClient下载图片或者数据,因此HttpClient的使用非常重要。

二、HttpClient的网络请求流程

HttpClient的网络请求流程其实也很简单,就是创建HttpClient对象、创建HttpGet/HttpPost对象,最后执行请求并处理响应。具体流程及代码如下:

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
String result = EntityUtils.toString(httpEntity);

首先,我们需要使用HttpClients.createDefault()方法创建一个CloseableHttpClient对象。创建完成后,就可以使用HttpGet或者HttpPost对象进行请求的创建了。

这里以HttpGet为例,使用HttpGet对象可以通过构造函数或者setURI()方法设置请求url。执行请求后,返回一个HttpResponse对象,可以通过获取HttpEntity来获取响应数据。最后使用EntityUtils.toString()方法将HttpEntity转换成String,在进行后续处理。

三、设置请求参数

HttpClient可以非常灵活地定制请求参数,如设置请求头、请求体、连接超时、读取超时、代理等等,下面我们将一一介绍。

1. 设置请求头

我们可以使用setHeader()方法进行自定义请求头,或者使用setDefaultHeaders()方法设置默认请求头,代码如下:

HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
httpGet.setHeader("Referer", referer);

这里我们设置了User-Agent和Referer两个请求头。User-Agent是指浏览器类型,在不同浏览器中会有不同的值。Referer是指请求发出时所在页面的URL地址,是反映当前请求所在页面的重要标识。

2. 设置请求体

HTTP的POST请求通常需要在请求体中传递数据,HttpClient可以通过setEntity()方法设置请求体。而常用的方法是使用UrlEncodedFormEntity来传递键值对参数,代码如下:

HttpPost httpPost = new HttpPost(url);
List list = new ArrayList
   ();
list.add(new BasicNameValuePair("username", "123456"));
list.add(new BasicNameValuePair("password", "abcdef"));
HttpEntity httpEntity = new UrlEncodedFormEntity(list);
httpPost.setEntity(httpEntity);
HttpResponse httpResponse = httpClient.execute(httpPost);
String result = EntityUtils.toString(httpResponse.getEntity());

   
  

这里我们使用HttpPost对象,并创建一个List集合来存储键值对参数,最后使用UrlEncodedFormEntity将键值对文本转换为HTTP请求实体。

3. 设置连接超时和读取超时

HttpClient可以进行连接超时和读取超时设置,以确保正常的请求服务和避免请求超时。实现代码如下:

RequestConfig.Builder builder = RequestConfig.custom();
builder.setConnectTimeout(10000);
builder.setSocketTimeout(30000);
RequestConfig requestConfig = builder.build();
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(requestConfig);
HttpResponse httpResponse = httpClient.execute(httpGet);

这里我们通过RequestConfig.Builder进行设置超时时间,设置了10秒的连接超时和30秒的读取超时,最后通过setConfig()方法设置到HttpGet对象中。

4. 设置代理

HttpClient也可以设置代理,以实现一些防爬虫技巧。可以使用HttpHost类来代表代理的主机和端口。代码如下:

HttpHost proxy = new HttpHost("127.0.0.1", 8888);
RequestConfig requestConfig = RequestConfig.custom().setProxy(proxy).build();
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(requestConfig);
HttpResponse httpResponse = httpClient.execute(httpGet);

这里我们使用HttpHost对象来表示代理主机和端口,然后将其设置到RequestConfig中,并使用setConfig()方法将配置设置到HttpGet对象中。

四、常见问题处理

1. Https请求

HttpClient访问Https请求需要导入SSL证书,否则会报如下异常:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target

我们可以通过加入信任所有证书的方式解决该问题。代码如下:

public static CloseableHttpClient createSSLClientDefault(){
    SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
        public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            return true;
        }
    }).build();
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
    return HttpClients.custom().setSSLSocketFactory(sslsf).build();
}

其中TrustStrategy表示完全信任请求的网站,也可以自定义信任证书库。

2. 下载文件

HttpClient也可以用来下载文件。我们可以使用HttpGet方法获取InputStream,然后将其写入文件。代码如下:

HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
InputStream inputStream = httpResponse.getEntity().getContent();
FileOutputStream fos = new FileOutputStream("D:/test.jpg");
byte[] buffer = new byte[4096];
int length;
while ((length = inputStream.read(buffer)) != -1) {
    fos.write(buffer, 0, length);
}
fos.flush();
inputStream.close();
fos.close();

3. 大文件下载

对于大文件下载,我们可以使用HttpClient的Range请求处理,分段读取数据,减少网络传输的压力。代码如下:

HttpGet httpGet = new HttpGet(url);
httpGet.addHeader("Range", "bytes=0-1024000");
HttpResponse httpResponse = httpClient.execute(httpGet);
InputStream inputStream = httpResponse.getEntity().getContent();
FileOutputStream fos = new FileOutputStream("D:/test.jpg");
byte[] buffer = new byte[4096];
int length;
while ((length = inputStream.read(buffer)) != -1) {
    fos.write(buffer, 0, length);
}
fos.flush();
inputStream.close();
fos.close();

这里我们使用Range请求,限制文件大小为0-1024000字节,就可以分段下载了。

总结

上述就是HttpClient下载的详细介绍,从HttpClient的简介、网络请求流程、设置请求参数、常见问题处理等多个方面做了阐述。掌握了HttpClient下载的使用方法,对于爬虫、Android开发等领域都非常重要。