2KB项目,专业的源码交易网站 帮助 收藏 每日签到

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

  • 时间:2019-01-23 18:44 编辑:2KB 来源:2KB.COM 阅读:361
  • 扫一扫,手机访问
  • 分享
摘要:
Android 英文原文:Android HTTP Client: GET, POST, Download, Upload, Multipart Request

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

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

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

GET 和POST 请求

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

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

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

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

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

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

InputStream is = con.getInputStream();
byte[] b = new byte[1024];
while ( is.read(b) != -1)
  buffer.append(new String(b));
con.disconnect();
现在所有东西都非常简单,但我们要记住一件事情:创建一个HTTP连接比较耗时的操作,有时候可能需要很长时间所以我们不能在主线程里运行它,否则我们会得到一个ANR (Application Not Responding)问题。要解决这个问题,我们可以用一个AsyncTask。
private class SendHttpRequestTask extends AsyncTask<String, Void, String>{
  
  @Override
  protected String doInBackground(String... params) {
   String url = params[0];
   String name = params[1];
   String data = sendHttpRequest(url, name);
   return data;
  }

  @Override
  protected void onPostExecute(String result) {
   edtResp.setText(result);
   item.setActionView(null);   
  }
}
运行APP我们得到了:

android_httpclient_post_get_1 android_httpclient_post_get_2

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

android_tomcat_post_log

从服务器下载数据

最常见的场景之一是一个Android APp需要从一个远程服务器下载一些数据。我们假设我们需要从服务器下载一个图片。在这种情况下我们就总得使用 AsyncTask来完成我们的操作,代码如下: 
public byte[] downloadImage(String imgName) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
        System.out.println("URL ["+url+"] - Name ["+imgName+"]");
        
        HttpURLConnection con = (HttpURLConnection) ( new URL(url)).openConnection();
        con.setRequestMethod("POST");
        con.setDoInput(true);
        con.setDoOutput(true);
        con.connect();
        con.getOutputStream().write( ("name=" + imgName).getBytes());
        
        InputStream is = con.getInputStream();
        byte[] b = new byte[1024];
        
        while ( is.read(b) != -1)
            baos.write(b);
        
        con.disconnect();
    }
    catch(Throwable t) {
        t.printStackTrace();
    }
    
    return baos.toByteArray();
}
这个方法用下面的方式来调用:
private class SendHttpRequestTask extends AsyncTask<String, Void, byte[]> {

    
    @Override
    protected byte[] doInBackground(String... params) {
        String url = params[0];
        String name = params[1];
        
        HttpClient client = new HttpClient(url);
        byte[] data = client.downloadImage(name);
        
        return data;
    }

    @Override
    protected void onPostExecute(byte[] result) {
        Bitmap img = BitmapFactory.decodeByteArray(result, 0, result.length);
        imgView.setImageBitmap(img);
        item.setActionView(null);
        
    }
   
}
运行我们的App:

android_httpclient_post_download

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

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

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

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

public void connectForMultipart() throws Exception {
    con = (HttpURLConnection) ( new URL(url)).openConnection();
    con.setRequestMethod("POST");
    con.setDoInput(true);
    con.setDoOutput(true);
    con.setRequestProperty("Connection", "Keep-Alive");
    con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
    con.connect();
    os = con.getOutputStream();
}

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

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

public void addFormPart(String paramName, String value) throws Exception {
  writeParamData(paramName, value);
}

private void writeParamData(String paramName, String value) throws Exception {
    os.write( (delimiter + boundary + "
").getBytes());
    os.write( "Content-Type: text/plain
".getBytes());
    os.write( ("Content-Disposition: form-data; name="" + paramName + ""
").getBytes());;
    os.write( ("
" + value + "
").getBytes());
    
}
这里 
private String delimiter = "--";
private String boundary =  "SwA"+Long.toString(System.currentTimeMillis())+"SwA";
加入一个文件我们能够这样使用:
public void addFilePart(String paramName, String fileName, byte[] data) throws Exception {
    os.write( (delimiter + boundary + "
").getBytes());
    os.write( ("Content-Disposition: form-data; name="" + paramName +  ""; filename="" + fileName + ""
"  ).getBytes());
    os.write( ("Content-Type: application/octet-stream
"  ).getBytes());
    os.write( ("Content-Transfer-Encoding: binary
"  ).getBytes());
    os.write("
".getBytes());
   
    os.write(data);
    
    os.write("
".getBytes());
}
因此在我们的App里就这样:
private class SendHttpRequestTask extends AsyncTask<String, Void, String> {

    
    @Override
    protected String doInBackground(String... params) {
        String url = params[0];
        String param1 = params[1];
        String param2 = params[2];
        Bitmap b = BitmapFactory.decodeResource(UploadActivity.this.getResources(), R.drawable.logo);
        
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        b.compress(CompressFormat.PNG, 0, baos);

        try {
            HttpClient client = new HttpClient(url);
            client.connectForMultipart();
            client.addFormPart("param1", param1);
            client.addFormPart("param2", param2);
            client.addFilePart("file", "logo.png", baos.toByteArray());
            client.finishMultipart();
            String data = client.getResponse();
        }
        catch(Throwable t) {
            t.printStackTrace();
        }
        
        return null;
    }

    @Override
    protected void onPostExecute(String data) {            
        item.setActionView(null);        
    }
   
}
运行它我们就看到:

android_tomcat_post_upload_log android_httpclient_post_upload
源代码 @ github. 本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。


2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务

  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【计算机/互联网|】Nginx出现502错误(2020-01-20 21:02)
【计算机/互联网|】网站运营全智能软手V0.1版发布(2020-01-20 12:16)
【计算机/互联网|】淘宝这是怎么了?(2020-01-19 19:15)
【行业动态|】谷歌关闭小米智能摄像头,因为窃听器显示了陌生人家中的照片(2020-01-15 09:42)
【行业动态|】据报道谷歌新闻终止了数字杂志,退还主动订阅(2020-01-15 09:39)
【行业动态|】康佳将OLED电视带到美国与LG和索尼竞争(2020-01-15 09:38)
【行业动态|】2020年最佳AV接收机(2020-01-15 09:35)
【行业动态|】2020年最佳流媒体设备:Roku,Apple TV,Firebar,Chromecast等(2020-01-15 09:31)
【行业动态|】CES 2020预览:更多的流媒体服务和订阅即将到来(2020-01-08 21:41)
【行业动态|】从埃隆·马斯克到杰夫·贝佐斯,这30位人物定义了2010年代(2020-01-01 15:14)
联系我们

Q Q: 7090832

电话:400-0011-990

邮箱:7090832@qq.com

时间:9:00-23:00

联系客服
商家入住 服务咨询 投拆建议 联系客服
0577-67068160
手机版

扫一扫进手机版
返回顶部