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(); } } } }