HttpClient是Apache对Java提供方法的一些封装, 在Android2.2版本之前,建议使用。
特点:上传文件很便利, 不过须要导入apache-mime4j-0.6.jar和httpmime-4.0.jar。注意默认不带gzip压缩。
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(); } } } }