Android中HttpClient網絡請求

HttpClient是Apache對Java提供方法的一些封裝, 在Android2.2版本以前,建議使用。
特色:上傳文件很便利, 不過需要導入apache-mime4j-0.6.jar和httpmime-4.0.jar。注意默認不帶gzip壓縮。java

public class HttpClientUtil {
 public static final int READ_TIMEOUT = 30*1000;
 public static final int CONNECT_TIMEOUT = 10*1000;
 public static final int EXCEPTION_ERR = 888;
 // 文件下載的狀態
 public static final int DOWNLOAD_FAIL = -1;  //下載失敗
 public static final int DOWNLOAD_PART = 0;  //下載了一部分
 public static final int DOWNLOAD_COMPLETE = 1;  //徹底下載
 
 /**
  * 採用POST方式提交數據流
  * @param handler
  *             用消息發送機制返回HTTP Response結果
  * @param urlStr
  *             連接
  * @param params
  *             提交到服務器的參數
  * @param files
  *             提交到服務器的文件
  * */
 public static void postWithHttpClient(Handler handler, String urlStr,
   Map<String, String> params, Map<String, File> files){
  Message msg = handler.obtainMessage();
  HttpPost post = null;
  try{
   post = new HttpPost(urlStr);
   HttpParams http_param = new BasicHttpParams();
   HttpConnectionParams.setConnectionTimeout(http_param, CONNECT_TIMEOUT);//socket創建連接的超時時間。
   HttpConnectionParams.setSoTimeout(http_param, CONNECT_TIMEOUT);//創建連接成功後,獲取response的返回等待時間。
   ConnManagerParams.setTimeout(http_param, CONNECT_TIMEOUT);//從鏈接池中取鏈接的超時時間 
   post.setParams(http_param);
   MultipartEntity entity = new MultipartEntity();
   if (params != null) { //添加參數
    for (Map.Entry<String, String> entry : params.entrySet()) {
     entity.addPart(entry.getKey(), new StringBody(entry.getValue(), Charset.forName("UTF-8")));
    }
   }
   if (files != null) { //添加文件
    for (Map.Entry<String, File> entry : files.entrySet()) {
     entity.addPart(entry.getKey(), new FileBody(entry.getValue(), entry.getValue().getName()));
    }
   }
   post.setEntity(entity);
  
   HttpClient client = new DefaultHttpClient();
   HttpResponse response = client.execute(post);
   int statuscode = response.getStatusLine().getStatusCode();
   msg.what = statuscode;
   HttpEntity e = response.getEntity();
   if ( e!=null ) {
    msg.obj = EntityUtils.toString(e);
   } else {
    msg.obj = "";
   }
  } catch (Exception e) {
   msg.what = EXCEPTION_ERR;
   msg.obj = e.getMessage();
  } finally {
   msg.sendToTarget();
   if( post != null ){
    post.abort();
   }
  }
 }
 
 /**
  * 採用GET方式獲取數據流
  * @param handler
  *             用消息發送機制返回HTTP Response結果
  * @param urlStr
  *             連接
  * */
 public static void getWithHttpClient(String url, Handler handler) {
  Message msg = handler.obtainMessage();
  HttpGet httpGet = null;
  try {  
   httpGet= new HttpGet(url);
   HttpParams httpParams = new BasicHttpParams();
   HttpConnectionParams.setConnectionTimeout(httpParams, CONNECT_TIMEOUT);
   HttpConnectionParams.setSoTimeout(httpParams, CONNECT_TIMEOUT);
   httpGet.setParams(httpParams);
   HttpClient httpClient = new DefaultHttpClient();
   HttpResponse response = httpClient.execute(httpGet);
   int statusCode = response.getStatusLine().getStatusCode();
   msg.what = statusCode;
   HttpEntity entity = response.getEntity();
   if (entity!=null) {
    msg.obj = EntityUtils.toString(entity);
   } else {
    msg.obj = "";
   }
  } catch (Exception e) {
   msg.what = EXCEPTION_ERR;
   msg.obj = e.getMessage();
  } finally {
   msg.sendToTarget();
   if( httpGet!=null ){
    httpGet.abort();
   }
  }
 }
 
 /**
  * 一次性所有下載
  * 1. 使用GET方法下載
  * 2. 不要設置SoTimeout,若是要設置,最好時間長一些,由於大文件的下載原本就耗時
  * 3. 下載過程採用一邊讀輸入流,一邊寫入文件的方法,節約內存
  * 4. 若是隻下載了一部分就被中斷,可是服務器不支持斷點續傳的話,必須從新下載
  */
 public static int downloadWithHttpClient(DownloadFileInfo fileInfo) {
  HttpGet httpGet = null;
  InputStream is = null;
  RandomAccessFile savedfile = null;
  try {
   httpGet = new HttpGet(fileInfo.mURL);
   HttpParams httpParams = new BasicHttpParams();
   HttpConnectionParams.setConnectionTimeout(httpParams, CONNECT_TIMEOUT);
   httpGet.setParams(httpParams);
   
   HttpClient httpClient = new DefaultHttpClient();
   HttpResponse response = httpClient.execute(httpGet);
   //保存文件的標示
   Header[] headers = response.getAllHeaders();
   int headerSize = headers.length;
   for( int i = 0; i < headerSize; ++i ) {
    if (headers[i].getName().equalsIgnoreCase("ETag")){
     String etag = headers[i].getValue();
     fileInfo.mEtag = etag;
     break;
    }
   }
   
   //新建須要寫入的RandomAccessFile
   File dir = new File(fileInfo.mFilePath);
   if(!dir.exists()){
    dir.mkdirs();
   }
   File file = new File(fileInfo.mFilePath+File.separator+fileInfo.mFileName);
   if(!file.exists()){
    file.createNewFile();
   }
   savedfile = new RandomAccessFile(file,"rwd");
   
   int responseCode = response.getStatusLine().getStatusCode();
   if ( responseCode == 200 ) {//用來表示請求成功.
    long len = response.getEntity().getContentLength();
    if( len <= 0 ) {
     return DOWNLOAD_FAIL;
    }
    fileInfo.mCompleteFileLength = len;
    
    int readSize = 0;
    byte[] buffer = new byte[1024];//1k內存
    is = response.getEntity().getContent();
    while( ( readSize = is.read(buffer) ) != -1 ) {
     // 循環從輸入流中讀1k數據,寫入文件
     savedfile.write(buffer, 0, readSize);
     fileInfo.mCurrentFileLength += readSize;
    }
   } else {
    return DOWNLOAD_FAIL;
   }
   int status = DOWNLOAD_FAIL;
   if( fileInfo.mCurrentFileLength > 0 ) {
    if( fileInfo.mCurrentFileLength == fileInfo.mCompleteFileLength ) {
     status = DOWNLOAD_COMPLETE;
    } else {
     status = DOWNLOAD_PART;
    }
   }
   return status;
  } catch (Exception e) {
   e.printStackTrace();
   int status = DOWNLOAD_FAIL;
   if( fileInfo.mCurrentFileLength > 0 ) {
    status = DOWNLOAD_PART;
   }
   return status;
  } finally {
   if( httpGet != null ) {
    httpGet.abort();
   }
   if( is != null ) {
    try {
     is.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
   if( savedfile != null ) {
    try {
     savedfile.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }
 }
 
 /** 
  * 斷點續傳下載
  **/
 public static int downloadRangeWithHttpClient(DownloadFileInfo fileInfo) {
  HttpGet httpGet = null;
  InputStream is = null;
  RandomAccessFile savedfile = null;
  try {
   httpGet = new HttpGet(fileInfo.mURL);
   HttpParams httpParams = new BasicHttpParams();
   HttpConnectionParams.setConnectionTimeout(httpParams, CONNECT_TIMEOUT);
   httpGet.setParams(httpParams);
   
   long startPos = fileInfo.mCurrentFileLength;//開始位置
   httpGet.addHeader("Range", "bytes=" + startPos + "-"); //設置獲取實體數據的範圍
   
   //新建須要寫入的RandomAccessFile
   File file = new File(fileInfo.mFilePath+File.separator+fileInfo.mFileName);
   savedfile = new RandomAccessFile(file,"rwd");
   savedfile.seek(startPos);
   
   HttpClient httpClient = new DefaultHttpClient();
   HttpResponse response = httpClient.execute(httpGet);
    
   int responseCode = response.getStatusLine().getStatusCode();
   if ( responseCode == 206 ) {//斷點續傳成功的反饋值是206,不是200
    long len = response.getEntity().getContentLength();
    if( len <= 0 ) {
     return DOWNLOAD_FAIL;
    }
    
    byte[] buffer = new byte[1024];
    int readSize = 0;
    is = response.getEntity().getContent();
    while( (readSize=is.read(buffer)) != -1 ) {
     savedfile.write(buffer, 0, readSize);
     fileInfo.mCurrentFileLength += readSize;
    }
   } else {
    return DOWNLOAD_FAIL;
   }
   int status = DOWNLOAD_FAIL;
   if( fileInfo.mCurrentFileLength > 0 ) {
    if( fileInfo.mCurrentFileLength == fileInfo.mCompleteFileLength ) {
     status = DOWNLOAD_COMPLETE;
    } else {
     status = DOWNLOAD_PART;
    }
   }
   return status;
  } catch (Exception e) {
   e.printStackTrace();
   int status = DOWNLOAD_FAIL;
   if( fileInfo.mCurrentFileLength > 0 ) {
    status = DOWNLOAD_PART;
   }
   return status;
  } finally {
   if (httpGet!=null){
    httpGet.abort();
   }
   if(is!=null){
    try {
     is.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
   if(savedfile!=null){
    try {
     savedfile.close();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }
 }
 
 /**
  * 判斷是否能夠斷點續傳
  * 
  * @param DownloadFileInfo 保存下載信息:
  *    mURL:下載連接
  *    mFilePath:指定下載文件保存路徑
  *    mFileName:下載文件的文件名
  *    mCompleteFileLength:待下載文件的Size
  *    mCurrentFileLength:已經下載的文件的Size,用於斷點續傳
  *    mEtag:服務器爲某個文件生產的惟一標識值,每次文件有更新該值就會變化。
  * */
 public static boolean shouldRangeDownload(DownloadFileInfo fileInfo){
  File file = new File(fileInfo.mFilePath+File.separator+fileInfo.mFileName);
  if(!file.exists()){
   // 原來下載的文件已經被刪除了,從新下載
   fileInfo.clearFileSizeRecord();
   return false;
  }
  HttpGet httpGet = null;
  try {
   httpGet = new HttpGet(fileInfo.mURL);
   HttpClient httpClient = new DefaultHttpClient();
   HttpResponse response = httpClient.execute(httpGet);
   
   Header[] headers = response.getAllHeaders();
   boolean acceptRangesIsBytes = false;
   boolean eTagChanged = true;
   int headerSize = headers.length;
   for( int i = 0; i < headerSize; ++i ) {
    if(headers[i].getName().equalsIgnoreCase("Accept-Ranges")){
     if(headers[i].getValue().equalsIgnoreCase("bytes")){
      acceptRangesIsBytes = true;
     }
    } else if (headers[i].getName().equalsIgnoreCase("ETag")){
     if(fileInfo.mEtag!=null && headers[i].getValue().equalsIgnoreCase(fileInfo.mEtag)){
      eTagChanged = false;
     }
    }
   }
   if( acceptRangesIsBytes == true && eTagChanged == false ) {
    return true;
   } else {
    // 1. 服務器不支持斷點續傳
    // 2. ETag改變了
    // 應該從新下載整個文件
    return false;
   }
  } catch (Exception e) {
   return false;
  } finally {
   if( httpGet!=null ){
    httpGet.abort();
   }
  }
 }
}
相關文章
相關標籤/搜索