在这篇文章中,我想描述如何使用Apache库构建HTTP客户端 。 在我的一篇文章中,我描述了如何使用HttpUrlConnection创建客户端。 使用Apache库,我想解释一下如何发出POST请求 , 下载图像和上传多部分二进制数据 。 此外,我将描述如何交换cookie。 因此涵盖的主题是:
- POST请求
- 下载二进制数据
- 上传二进制数据
- 交换Cookie
Apache库是Android SDK附带的外部库,可简化发出HTTP请求的任务。
POST请求
我们已经知道POST和GET是我们可以用来与远程服务器交换数据的基本方法。例如,我将一些文本格式的数据发送到远程服务器(到目前为止)。 因此,第一步是创建一个DefaultHttpClient ,它使用包装器发送数据。
HttpClient client = new DefaultHttpClient();
一旦有了客户,就必须实例化一个处理POST请求的类:
HttpPost post = new HttpPost(url);
url是我们要调用的URL。 要发送数据,我们只需创建一个列表
NameValuePair一个简单的类,其中包含我们要发送的参数的名称和值。
List<NameValuePair> nvList = new ArrayList<NameValuePair>();
BasicNameValuePair bnvp = new BasicNameValuePair("name", name);
// We can add more
nvList.add(bnvp);
在这种情况下,在第2行,我们将参数的名称设置为name,然后如前所述将bnvp添加到列表中。 现在,我们已经构建了列表并将其设置在我们的发帖请求中,以便可以发送它:
post.setEntity(new UrlEncodedFormEntity(nvList));
在这种情况下,我们使用Url编码对参数进行编码。 最后一步是通过我们的DefaultHttpClient实例执行请求。 结果,我们获得了一个HttpResponse ,可用于读取请求的结果:
HttpResponse resp = client.execute(post);
要读取响应,我们可以获取InputStream(第1行)并以这种方式使用它读取数据:
InputStream is = resp.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder str = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null){
str.append(line + "\n");
}
is.close();
buffer.append(str.toString());
最后,我们有一个字符串可用于更新UI。
我们必须记住,此操作可能很耗时,因此我们必须在AsyncTask中执行此请求。 有关更多信息,请阅读“ Android HTTP客户端:GET,POST,下载,上传,多部分请求 ”一文。这足以说明我们目前所做的所有工作都应在doInBackground方法内。 运行示例,我们有:
服务器端 |
下载二进制数据
另一个常见的操作是从服务器下载二进制数据。 在这种情况下,我们要从服务器下载图像并将其显示在我们的UI中。
操作非常简单,因为在这种情况下,我们必须发出HTTP Post请求,传递图像名称(第7-10行)并读取二进制响应(第15-28行):
@Override
protected byte[] doInBackground(String... params) {
String url = params[0];
String name = params[1];
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
List<NameValuePair> paramList = new ArrayList<NameValuePair>();
paramList.add(new BasicNameValuePair("name", name));
byte[] data = null;
try {
post.setEntity(new UrlEncodedFormEntity(paramList));
HttpResponse resp = client.execute(post);
InputStream is = resp.getEntity().getContent();
int contentSize = (int) resp.getEntity().getContentLength();
System.out.println("Content size ["+contentSize+"]");
BufferedInputStream bis = new BufferedInputStream(is, 512);
data = new byte[contentSize];
int bytesRead = 0;
int offset = 0;
while (bytesRead != -1 && offset < contentSize) {
bytesRead = bis.read(data, offset, contentSize - offset);
offset += bytesRead;
}
}
catch(Throwable t) {
// Handle error here
t.printStackTrace();
}
return data;
}
在第17行,我们读取响应长度,以便我们可以创建具有相同大小的字节数组(请参见第21行),然后在第19行,我们创建缓冲的输入流以读取响应流。 然后,我们只需读取填充数据字节数组的响应即可。 结果,我们有:
上传二进制数据
这是最有趣的方面之一。 要处理此操作,我们需要添加一个外部库以简化任务。 这是相对于android native api使用apache http client的缺点。 另一方面,我们看到android native api无法处理多部分请求,因此我们必须从零开始。 使用此库,我们可以简化过程,但最终导致更大的apk。 该库是开源的,称为httpmime-xxx.jar 。 您可以在这里下载。 请记住将其添加到您的项目中,并且必须将其导出(请参阅Eclipse中的订购和导出)。 作为示例,我们创建一个包含一些文本数据和图像的多部分请求。 因此,我们总是开始创建DefaultHttpClient和HttpPost:
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
现在我们必须创建称为Entity的帖子内容:
MultipartEntity multiPart = new MultipartEntity();
然后添加单个部分:两个是文本数据,一个是二进制数据(我们要上传的图像):
multiPart.addPart("param1", new StringBody(param1));
multiPart.addPart("param2", new StringBody(param2));
multiPart.addPart("file", new ByteArrayBody(baos.toByteArray(), "logo.png"));
注意,在第3行,我们使用ByteArrayBody创建了一个包含二进制数据的零件。 我们使用创建的数据填充帖子内容:
post.setEntity(multiPart);
然后我们只需将其发送(或发布)到服务器:
client.execute(post);
运行我们拥有的应用程序:
服务器端 |
交换Cookie
HTTP协议中一个有趣的方面是cookie管理 。 我们知道HTTP是无状态协议,因此使用Cookie,我们可以在HTTP请求中保留一些信息。 作为示例,我们可以假设发出两个HTTP请求:一个调用URL,服务器返回包含某些信息的cookie,另一个请求将cookie发送回服务器。
第一个请求非常简单:
HttpPost post = new HttpPost(url);
HttpResponse resp = client.execute(post);
然后,我们读取Cookie(第1,3行):
CookieStore store = ((DefaultHttpClient) client).getCookieStore();
List<Cookie> cookies = store.getCookies();
if (cookies != null) {
for (Cookie c : cookies) {
System.out.println("Name ["+c.getName()+"] - Val ["+c.getValue()+"]
- Domain ["+c.getDomain()+"] - Path ["+c.getPath()+"]");
store.addCookie(c);
}
}
在第1行,我们仅获得存储cookie的cookie存储。 在第3行,我们检索cookie列表。 在第二个发布请求中,我们必须维护在第一个请求中检索到的cookie,因此我们需要:
HttpContext ctx = new BasicHttpContext();
ctx.setAttribute(ClientContext.COOKIE_STORE, store);
// Post again with cookie
HttpPost post1 = new HttpPost(url);
client.execute(post1);
HttpResponse resp1 = client.execute(post, ctx);
在第1行,我们创建BasicHttpContext来处理Cookie,在第2行,我们在上下文中设置存储,最后在第7行,我们也执行了传递上下文的请求。
我们必须注意的一件事是DefaultHttpClient始终相同,以便我们可以重复使用cookie 。
运行示例,我们有:
| |
客户端Cookie输出 | 服务器端Cookie输出 |
源代码可从github获得 。
翻译自: https://www.javacodegeeks.com/2013/06/android-apache-http-client.html