HttpClient

运用InputStreamEntity 边读取边上传文件


List<NameValuePair> params = new ArrayList<NameValuePair>();

定义了一个list,该list的数据类型是NameValuePair(简单名称值对节点类型),这个代码多处用于Java像url发送Post请求。在发送post请求时用该list来存放参数。
发送请求的大致过程如下:

String url=" http://www.baidu.com ";

HttpPost httppost=new HttpPost(url); //建立HttpPost对象

List<NameValuePair> params=new ArrayList<NameValuePair>();
//建立一个NameValuePair数组,用于存储欲传送的参数

params.add(new BasicNameValuePair("pwd","2544"));
//添加参数

httppost.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8));
//设置编码

HttpResponse response=new DefaultHttpClient().execute(httppost);
//发送Post,并返回一个HttpResponse对象

 关于Httpclient的使用总结如下:

  1. (1)当HttpClient的实例不再需要时,可以使用连接管理器关闭   
  2. httpclient.getConnectionManager().shutdown();    
  1. (1)当HttpClient的实例不再需要时,可以使用连接管理器关闭  
  2. httpclient.getConnectionManager().shutdown();    
(1)当HttpClient的实例不再需要时,可以使用连接管理器关闭
httpclient.getConnectionManager().shutdown();  
  1. (2)针对HTTPs的协议的HttpClient请求必须用户和密码   
  2.  httpclient.getCredentialsProvider()   
  3.             .setCredentials(new AuthScope("localhost"443),    
  4.                 new UsernamePasswordCredentials("username""password"));  
  1. (2)针对HTTPs的协议的HttpClient请求必须用户和密码  
  2.  httpclient.getCredentialsProvider()  
  3.             .setCredentials(new AuthScope("localhost"443),   
  4.                 new UsernamePasswordCredentials("username""password"));  
(2)针对HTTPs的协议的HttpClient请求必须用户和密码
 httpclient.getCredentialsProvider()
            .setCredentials(new AuthScope("localhost", 443), 
                new UsernamePasswordCredentials("username", "password"));
  1. (3)如果不想获取HTTPClient返回的信息   
  2.    httpclient.abort();  
  1. (3)如果不想获取HTTPClient返回的信息  
  2.    httpclient.abort();  
(3)如果不想获取HTTPClient返回的信息
   httpclient.abort();
 
  1.       
  2. (4)httpclient传送文件的方式   
  3.         HttpClient httpclient = new DefaultHttpClient();   
  4.         HttpPost httppost = new HttpPost("http://www.apache.org");   
  5.         File file = new File(args[0]);   
  6.         InputStreamEntity reqEntity = new InputStreamEntity(   
  7.                 new FileInputStream(file), -1);   
  8.         reqEntity.setContentType("binary/octet-stream");   
  9.         reqEntity.setChunked(true);   
  10.         // It may be more appropriate to use FileEntity class in this particular   
  11.         // instance but we are using a more generic InputStreamEntity to demonstrate  
  12.         // the capability to stream out data from any arbitrary source  
  13.         //    
  14.         // FileEntity entity = new FileEntity(file, "binary/octet-stream");   
  15.         httppost.setEntity(reqEntity);   
  16.         System.out.println("executing request " + httppost.getRequestLine());   
  17.         HttpResponse response = httpclient.execute(httppost);  
  1.      
  2. (4)httpclient传送文件的方式  
  3.         HttpClient httpclient = new DefaultHttpClient();  
  4.         HttpPost httppost = new HttpPost("http://www.apache.org");  
  5.         File file = new File(args[0]);  
  6.         InputStreamEntity reqEntity = new InputStreamEntity(  
  7.                 new FileInputStream(file), -1);  
  8.         reqEntity.setContentType("binary/octet-stream");  
  9.         reqEntity.setChunked(true);  
  10.         // It may be more appropriate to use FileEntity class in this particular   
  11.         // instance but we are using a more generic InputStreamEntity to demonstrate  
  12.         // the capability to stream out data from any arbitrary source  
  13.         //   
  14.         // FileEntity entity = new FileEntity(file, "binary/octet-stream");   
  15.         httppost.setEntity(reqEntity);  
  16.         System.out.println("executing request " + httppost.getRequestLine());  
  17.         HttpResponse response = httpclient.execute(httppost);  
   
(4)httpclient传送文件的方式
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost("http://www.apache.org");
        File file = new File(args[0]);
        InputStreamEntity reqEntity = new InputStreamEntity(
                new FileInputStream(file), -1);
        reqEntity.setContentType("binary/octet-stream");
        reqEntity.setChunked(true);
        // It may be more appropriate to use FileEntity class in this particular 
        // instance but we are using a more generic InputStreamEntity to demonstrate
        // the capability to stream out data from any arbitrary source
        // 
        // FileEntity entity = new FileEntity(file, "binary/octet-stream"); 
        httppost.setEntity(reqEntity);
        System.out.println("executing request " + httppost.getRequestLine());
        HttpResponse response = httpclient.execute(httppost);
 
  1. (5)获取Cookie的信息   
  2.         HttpClient httpclient = new DefaultHttpClient();   
  3.         // 创建一个本地Cookie存储的实例   
  4.         CookieStore cookieStore = new BasicCookieStore();   
  5.         //创建一个本地上下文信息   
  6.         HttpContext localContext = new BasicHttpContext();   
  7.         //在本地上下问中绑定一个本地存储   
  8.         localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);   
  9.         //设置请求的路径   
  10.         HttpGet httpget = new HttpGet("http://www.google.com/");    
  11.         //传递本地的http上下文给服务器   
  12.         HttpResponse response = httpclient.execute(httpget, localContext);   
  13.         //获取本地信息   
  14.         HttpEntity entity = response.getEntity();   
  15.         System.out.println(response.getStatusLine());   
  16.         if (entity != null) {   
  17.             System.out.println("Response content length: " + entity.getContentLength());   
  18.         }   
  19.         //获取cookie中的各种信息   
  20.         List<Cookie> cookies = cookieStore.getCookies();   
  21.         for (int i = 0; i < cookies.size(); i++) {   
  22.             System.out.println("Local cookie: " + cookies.get(i));   
  23.         }   
  24.         //获取消息头的信息   
  25.         Header[] headers = response.getAllHeaders();   
  26.         for (int i = 0; i<headers.length; i++) {   
  27.             System.out.println(headers[i]);   
  28.         }  
  1. (5)获取Cookie的信息  
  2.         HttpClient httpclient = new DefaultHttpClient();  
  3.         // 创建一个本地Cookie存储的实例  
  4.         CookieStore cookieStore = new BasicCookieStore();  
  5.         //创建一个本地上下文信息  
  6.         HttpContext localContext = new BasicHttpContext();  
  7.         //在本地上下问中绑定一个本地存储  
  8.         localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);  
  9.         //设置请求的路径  
  10.         HttpGet httpget = new HttpGet("http://www.google.com/");   
  11.         //传递本地的http上下文给服务器  
  12.         HttpResponse response = httpclient.execute(httpget, localContext);  
  13.         //获取本地信息  
  14.         HttpEntity entity = response.getEntity();  
  15.         System.out.println(response.getStatusLine());  
  16.         if (entity != null) {  
  17.             System.out.println("Response content length: " + entity.getContentLength());  
  18.         }  
  19.         //获取cookie中的各种信息  
  20.         List<Cookie> cookies = cookieStore.getCookies();  
  21.         for (int i = 0; i < cookies.size(); i++) {  
  22.             System.out.println("Local cookie: " + cookies.get(i));  
  23.         }  
  24.         //获取消息头的信息  
  25.         Header[] headers = response.getAllHeaders();  
  26.         for (int i = 0; i<headers.length; i++) {  
  27.             System.out.println(headers[i]);  
  28.         }  
(5)获取Cookie的信息
        HttpClient httpclient = new DefaultHttpClient();
        // 创建一个本地Cookie存储的实例
        CookieStore cookieStore = new BasicCookieStore();
        //创建一个本地上下文信息
        HttpContext localContext = new BasicHttpContext();
        //在本地上下问中绑定一个本地存储
        localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        //设置请求的路径
        HttpGet httpget = new HttpGet("http://www.google.com/"); 
        //传递本地的http上下文给服务器
        HttpResponse response = httpclient.execute(httpget, localContext);
        //获取本地信息
        HttpEntity entity = response.getEntity();
        System.out.println(response.getStatusLine());
        if (entity != null) {
            System.out.println("Response content length: " + entity.getContentLength());
        }
        //获取cookie中的各种信息
        List<Cookie> cookies = cookieStore.getCookies();
        for (int i = 0; i < cookies.size(); i++) {
            System.out.println("Local cookie: " + cookies.get(i));
        }
        //获取消息头的信息
        Header[] headers = response.getAllHeaders();
        for (int i = 0; i<headers.length; i++) {
            System.out.println(headers[i]);
        }
 
  1. (6)针对典型的SSL请求的处理   
  2.         DefaultHttpClient httpclient = new DefaultHttpClient();   
  3.         //获取默认的存储密钥类   
  4.         KeyStore trustStore  = KeyStore.getInstance(KeyStore.getDefaultType());    
  5.         //加载本地的密钥信息          
  6.         FileInputStream instream = new FileInputStream(new File("my.keystore"));    
  7.         try {   
  8.             trustStore.load(instream, "nopassword".toCharArray());   
  9.         } finally {   
  10.             instream.close();   
  11.         }   
  12.         //创建SSLSocketFactory,创建相关的Socket   
  13.         SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);   
  14.         //设置协议的类型和密钥信息,以及断开信息   
  15.         Scheme sch = new Scheme("https", socketFactory, 443);   
  16.         //在连接管理器中注册中信息   
  17.         httpclient.getConnectionManager().getSchemeRegistry().register(sch);  
  1. (6)针对典型的SSL请求的处理  
  2.         DefaultHttpClient httpclient = new DefaultHttpClient();  
  3.         //获取默认的存储密钥类  
  4.         KeyStore trustStore  = KeyStore.getInstance(KeyStore.getDefaultType());   
  5.         //加载本地的密钥信息         
  6.         FileInputStream instream = new FileInputStream(new File("my.keystore"));   
  7.         try {  
  8.             trustStore.load(instream, "nopassword".toCharArray());  
  9.         } finally {  
  10.             instream.close();  
  11.         }  
  12.         //创建SSLSocketFactory,创建相关的Socket  
  13.         SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);  
  14.         //设置协议的类型和密钥信息,以及断开信息  
  15.         Scheme sch = new Scheme("https", socketFactory, 443);  
  16.         //在连接管理器中注册中信息  
  17.         httpclient.getConnectionManager().getSchemeRegistry().register(sch);  
(6)针对典型的SSL请求的处理
        DefaultHttpClient httpclient = new DefaultHttpClient();
        //获取默认的存储密钥类
        KeyStore trustStore  = KeyStore.getInstance(KeyStore.getDefaultType()); 
        //加载本地的密钥信息       
        FileInputStream instream = new FileInputStream(new File("my.keystore")); 
        try {
            trustStore.load(instream, "nopassword".toCharArray());
        } finally {
            instream.close();
        }
        //创建SSLSocketFactory,创建相关的Socket
        SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
        //设置协议的类型和密钥信息,以及断开信息
        Scheme sch = new Scheme("https", socketFactory, 443);
        //在连接管理器中注册中信息
        httpclient.getConnectionManager().getSchemeRegistry().register(sch);
 
  1. (7)设置请求的参数的几种方式   
  2. A.在请求的路径中以查询字符串格式传递参数   
  3. B.在请求的实体中添加参数   
  4.         List <NameValuePair> nvps = new ArrayList <NameValuePair>();   
  5.         nvps.add(new BasicNameValuePair("IDToken1""username"));   
  6.         nvps.add(new BasicNameValuePair("IDToken2""password"));   
  7.         httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); 

  转载请标明出处 http://blog.csdn.net/shimiso


HTTP协议的chunked编码

      一般情况HTTP的Header包含Content-Length域来指明报文体的长度。如:

      image

     有时候服务生成HTTP回应是无法确定消息大小的,比如大文件的下载,或者后台需要复杂的逻辑才能全部处理页面的请求,这时用需要实时生成消息长度,服务器一般使用chunked编码。

     在进行Chunked编码传输时,在回复消息的Headers有transfer-coding域值为chunked,表示将用chunked编码传输内容。使用chunked编码的Headers如下(可以利用FireFox的FireBug插件或HttpWatch查看Headers信息,HttpWatch还可以查看chunked的个数):

     image

     chunked采用以下方式编码:

     Chunked-Body=*chunk 
"0"CRLF 
footer 
CRLF 
chunk=chunk-size[chunk-ext]CRLF 
chunk-dataCRLF 
hex-no-zero=<HEXexcluding"0"> 
chunk-size=hex-no-zero*HEX 
chunk-ext=*(";"chunk-ext-name["="chunk-ext-value]) 
chunk-ext-name=token 
chunk-ext-val=tokenquoted-string 
chunk-data=chunk-size(OCTET) 
footer=*entity-header

     编码使用若干个Chunk组成,由一个标明长度为0的chunk结束,每个Chunk有两部分组成,第一部分是该Chunk的长度和长度单位(一般不写),第二部分就是指定长度的内容,每个部分用CRLF隔开。在最后一个长度为0的Chunk中的内容是称为footer的内容,是一些没有写的头部内容。



chunked编码的基本方法是将大块数据分解成多块小数据,每块都可以自指定长度,其具体格式如下(BNF文法):
Chunked-Body = *chunk //0至多个chunk
last-chunk //最后一个chunk 
trailer //尾部
CRLF //结束标记符

chunk = chunk-size [ chunk-extension ] CRLF 
chunk-data CRLF
chunk-size = 1*HEX
last-chunk = 1*("0") [ chunk-extension ] CRLF

chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token | quoted-string
chunk-data = chunk-size(OCTET)
trailer = *(entity-header CRLF) 

解释:
Chunked-Body表示经过chunked编码后的报文体。报文体可以分为chunk, last-chunk,trailer和结束符四部分。chunk的数量在报文体中最少可以为0,无上限;每个chunk的长度是自指定的,即,起始的数据必然是16进制数字的字符串,代表后面chunk-data的长度(字节数)。这个16进制的字符串第一个字符如果是“0”,则表示chunk-size为0,该chunk为last-chunk,无chunk-data部分。可选的chunk-extension由通信双方自行确定,如果接收者不理解它的意义,可以忽略。
trailer是附加的在尾部的额外头域,通常包含一些元数据(metadata, meta means "about information"),这些头域可以在解码后附加在现有头域之后。
实例分析:
下面分析用ethereal抓包使用Firefox与某网站通信的结果(从头域结束符后开始):
Address 0.......................... f
000c0 31
000d0 66 66 63 0d 0a ............... // ASCII码:1ffc\r\n, chunk-data数据起始地址为000d5
很明显,“1ffc”为第一个chunk的chunk-size,转换为int为8188.由于1ffc后马上就是
CRLF,因此没有chunk-extension.chunk-data的起始地址为000d5, 计算可知下一块chunk的起始
地址为000d5+1ffc + 2=020d3,如下:
020d0 .. 0d 0a 31 66 66 63 0d 0a .... // ASCII码:\r\n1ffc\r\n
前一个0d0a是上一个chunk的结束标记符,后一个0d0a则是chunk-size和chunk-data的分隔符。
此块chunk的长度同样为8188, 依次类推,直到最后一块
100e0 0d 0a 31
100f0 65 61 39 0d 0a...... //ASII码:\r\n\1ea9\r\n
此块长度为0x1ea9 = 7849, 下一块起始为100f5 + 1ea9 + 2 = 11fa0,如下:
100a0 30 0d 0a 0d 0a //ASCII码:0\r\n\r\n
“0”说明当前chunk为last-chunk, 第一个0d 0a为chunk结束符。第二个0d0a说明没有trailer部分,整个Chunk-body结束。
解码流程:
对chunked编码进行解码的目的是将分块的chunk-data整合恢复成一块作为报文体,同时记录此块体的长度。
RFC2616中附带的解码流程如下:(伪代码)
length := 0 //长度计数器置0
read chunk-size, chunk-extension (if any) and CRLF //读取chunk-size, chunk-extension
//和CRLF
while(chunk-size > 0 ) { //表明不是last-chunk
read chunk-data and CRLF //读chunk-size大小的chunk-data,skip CRLF
append chunk-data to entity-body //将此块chunk-data追加到entity-body后
read chunk-size and CRLF //读取新chunk的chunk-size 和 CRLF
}
read entity-header //entity-header的格式为name:valueCRLF,如果为空即只有CRLF
while (entity-header not empty) //即,不是只有CRLF的空行
{
append entity-header to existing header fields
read entity-header
}
Content-Length:=length //将整个解码流程结束后计算得到的新报文体length
//作为Content-Length域的值写入报文中
Remove "chunked" from Transfer-Encoding //同时从Transfer-Encoding中域值去除chunked这个标记
length最后的值实际为所有chunk的chunk-size之和,在上面的抓包实例中,一共有八块chunk-size为0x1ffc(8188)的chunk,剩下一块为0x1ea9(7849),加起来一共73353字节。
注:对于上面例子中前几个chunk的大小都是8188,可能是因为:"1ffc" 4字节,"\r\n"2字节,加上块尾一个"\r\n"2字节一共8字节,因此一个chunk整体为8196,正好可能是发送端一次TCP发送的缓存大


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值