Android HTTP Client: GET, POST, Download, Upload, Multipart Request

来源:互联网 发布:皮诺切特 知乎 编辑:程序博客网 时间:2024/05/16 01:43

Android 的 HTTP 客户端:GET, POST, Download, Upload, Multipart Req...

英文原文:Android HTTP Client: GET, POST, Download, Upload, Multipart Request

标签: Android
0人收藏此文章, 我要收藏oschina 推荐于 14天前 (共 4 段, 翻译完成于 05-22) (0评) 
参与翻译(1人)
throwable
仅中文 | 中英文对照 | 仅英文 | 打印此文章

Android应用通常都要和远程服务器进行交互。最简单的方式是使用基于HTTP协议来传输信息。在一些场景里HTTP协议是非常有用的,就像从远程服务器下载一个图像或者上传一些二进制数据到服务器。Android应用程序使用GET或POST请求来发送数据。在这篇文章,我们想要分析怎样用HttpURLConnection来和一个远程服务器通信。

我们包含这3个主要主题:

  • GET 和POST 请求
  • 从远程服务器下载数据
  • 使用MultipartRequest上传数据到服务器
我们会用运行在Tomcat7.0里的3个简单Servlet来作为一个简单的服务器。我们不会讲到怎样使用API3.0来创建Servlet但源代码现在就会提供。
throwable
throwable
翻译于 14天前

0人顶

 翻译的不错哦!

GET 和POST 请求

GET和POST是HTTP协议里的基本模块。要使用这些类型的请求,我们首先需要打开一个连接到远程服务器连接: 
1HttpURLConnection con = (HttpURLConnection) ( new URL(url)).openConnection();
2con.setRequestMethod("POST");
3con.setDoInput(true);
4con.setDoOutput(true);
5con.connect();

我们在第一行得到HttpURLConnection,而在第二行我们设置了方法同时在最后连接到服务器。

一旦我们打开了连接,我们使用OutputStream在它上面写入东西。

1con.getOutputStream().write( ("name=" + name).getBytes());

我们已经知道参数是用键-值对来写入。

最后一步是使用InputStream读取返回。

1InputStream is = con.getInputStream();
2byte[] b = new byte[1024];
3while ( is.read(b) != -1)
4  buffer.append(new String(b));
5con.disconnect();
现在所有东西都非常简单,但我们要记住一件事情:创建一个HTTP连接比较耗时的操作,有时候可能需要很长时间所以我们不能在主线程里运行它,否则我们会得到一个ANR (Application Not Responding)问题。要解决这个问题,我们可以用一个AsyncTask。 
01private class SendHttpRequestTask extends AsyncTask<String, Void, String>{
02   
03  @Override
04  protected String doInBackground(String... params) {
05   String url = params[0];
06   String name = params[1];
07   String data = sendHttpRequest(url, name);
08   return data;
09  }
10 
11  @Override
12  protected void onPostExecute(String result) {
13   edtResp.setText(result);
14   item.setActionView(null);  
15  }
16}
运行APP我们得到了: 

android_httpclient_post_get_1android_httpclient_post_get_2
我们可以看到传了一个name到服务器同时它回复了一个典型的“Hello...”。在服务器端我们可以检查服务器是否正确接收到我们传递的参数。 

android_tomcat_post_log 
throwable
throwable
翻译于 14天前

0人顶

 翻译的不错哦!

从服务器下载数据

最常见的场景之一是一个Android APp需要从一个远程服务器下载一些数据。我们假设我们需要从服务器下载一个图片。在这种情况下我们就总得使用 AsyncTask来完成我们的操作,代码如下:  
01public byte[] downloadImage(String imgName) {
02    ByteArrayOutputStream baos = new ByteArrayOutputStream();
03    try {
04        System.out.println("URL ["+url+"] - Name ["+imgName+"]");
05         
06        HttpURLConnection con = (HttpURLConnection) ( new URL(url)).openConnection();
07        con.setRequestMethod("POST");
08        con.setDoInput(true);
09        con.setDoOutput(true);
10        con.connect();
11        con.getOutputStream().write( ("name=" + imgName).getBytes());
12         
13        InputStream is = con.getInputStream();
14        byte[] b = new byte[1024];
15         
16        while ( is.read(b) != -1)
17            baos.write(b);
18         
19        con.disconnect();
20    }
21    catch(Throwable t) {
22        t.printStackTrace();
23    }
24     
25    return baos.toByteArray();
26}
这个方法用下面的方式来调用: 
01private class SendHttpRequestTask extends AsyncTask<String, Void, byte[]> {
02 
03     
04    @Override
05    protected byte[] doInBackground(String... params) {
06        String url = params[0];
07        String name = params[1];
08         
09        HttpClient client = new HttpClient(url);
10        byte[] data = client.downloadImage(name);
11         
12        return data;
13    }
14 
15    @Override
16    protected void onPostExecute(byte[] result) {
17        Bitmap img = BitmapFactory.decodeByteArray(result, 0, result.length);
18        imgView.setImageBitmap(img);
19        item.setActionView(null);
20         
21    }
22    
23}
运行我们的App: 

android_httpclient_post_download 
throwable
throwable
翻译于 14天前

0人顶

 翻译的不错哦!

使用MultipartRequest来上传数据到服务器

这是处理http连接里最复杂的部分。原生的HttpURLConnection不处理这类型的请求。它发生在一个Android App要上传一些二进制数据到服务器。它也可能是一个app上传一个图片。在这种情况下,请求会更加复杂,因为一个“普通”的请求并不足够。我们要创建一个MultipartRequest。

一个MultipartRequest是由各种不同部分组成的请求,就像参数和二进制数据。我们要怎样去处理这些请求呢?

第一部就是打开一个连接告诉服务器我们想传递一些二进制信息:

01public void connectForMultipart() throws Exception {
02    con = (HttpURLConnection) ( new URL(url)).openConnection();
03    con.setRequestMethod("POST");
04    con.setDoInput(true);
05    con.setDoOutput(true);
06    con.setRequestProperty("Connection""Keep-Alive");
07    con.setRequestProperty("Content-Type""multipart/form-data; boundary=" + boundary);
08    con.connect();
09    os = con.getOutputStream();
10}

在第6行和第7行,我们指定了请求的content-type和另外一个叫boundary的字段。这个字段是一个字符串序列来分割不同部分的。

对于我们要加入的每个部分,我们需要指定它否是一个文本部分就像post参数或者它是一个而文件(二进制数据)。

01public void addFormPart(String paramName, String value) throws Exception {
02  writeParamData(paramName, value);
03}
04 
05private void writeParamData(String paramName, String value) throws Exception {
06    os.write( (delimiter + boundary + "\r\n").getBytes());
07    os.write( "Content-Type: text/plain\r\n".getBytes());
08    os.write( ("Content-Disposition: form-data; name=\"" + paramName + "\"\r\n").getBytes());;
09    os.write( ("\r\n" + value + "\r\n").getBytes());
10     
11}
这里  
1private String delimiter = "--";
2private String boundary =  "SwA"+Long.toString(System.currentTimeMillis())+"SwA";
加入一个文件我们能够这样使用: 
01public void addFilePart(String paramName, String fileName, byte[] data) throws Exception {
02    os.write( (delimiter + boundary + "\r\n").getBytes());
03    os.write( ("Content-Disposition: form-data; name=\"" + paramName +  "\"; filename=\""+ fileName + "\"\r\n"  ).getBytes());
04    os.write( ("Content-Type: application/octet-stream\r\n"  ).getBytes());
05    os.write( ("Content-Transfer-Encoding: binary\r\n"  ).getBytes());
06    os.write("\r\n".getBytes());
07    
08    os.write(data);
09     
10    os.write("\r\n".getBytes());
11}
因此在我们的App里就这样: 
01private class SendHttpRequestTask extends AsyncTask<String, Void, String> {
02 
03     
04    @Override
05    protected String doInBackground(String... params) {
06        String url = params[0];
07        String param1 = params[1];
08        String param2 = params[2];
09        Bitmap b = BitmapFactory.decodeResource(UploadActivity.this.getResources(), R.drawable.logo);
10         
11        ByteArrayOutputStream baos = new ByteArrayOutputStream();
12        b.compress(CompressFormat.PNG, 0, baos);
13 
14        try {
15            HttpClient client = new HttpClient(url);
16            client.connectForMultipart();
17            client.addFormPart("param1", param1);
18            client.addFormPart("param2", param2);
19            client.addFilePart("file""logo.png", baos.toByteArray());
20            client.finishMultipart();
21            String data = client.getResponse();
22        }
23        catch(Throwable t) {
24            t.printStackTrace();
25        }
26         
27        return null;
28    }
29 
30    @Override
31    protected voidonPostExecute(String data) {           
32        item.setActionView(null);       
33    }
34    
35}
运行它我们就看到: 

android_tomcat_post_upload_logandroid_httpclient_post_upload源代码 @ github.
throwable
throwable
翻译于 14天前

0人顶

 翻译的不错哦!