请尊重他人的劳动成果,转载请注明出处:
运行效果图:
我曾在《Android网络编程之使用HttpClient批量上传文件》一文中介绍过如何通过HttpClient实现多文件上传和服务器的接收。在上一篇主要使用Handler+HttpClient的方式实现文件上传。这一篇将介绍使用AsyncTask+HttpClient实现文件上传并监听上传进度。
监控进度实现:
首先定义监听器接口。如下所示:
/** * 进度监听器接口 */ public interface ProgressListener { public void transferred(longtransferedBytes); }
实现监控进度的关键部分就在于记录已传输字节数,所以我们需重载FilterOutputStream,重写其中的关键方法,实现进度监听的功能,如下所示,本例中首先重载的是HttpEntityWrapper,顾名思义,就是将需发送的HttpEntity打包,以便计算总字节数,代码如下:
package com.jph.ufh.utils; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; import org.apache.http.HttpEntity; import org.apache.http.entity.HttpEntityWrapper; /** * ProgressOutHttpEntity:输出流(OutputStream)时记录已发送字节数 * @author JPH * Date:2014.11.03 */ public class ProgressOutHttpEntity extends HttpEntityWrapper { /**进度监听对象**/ private final ProgressListener listener; public ProgressOutHttpEntity(final HttpEntity entity,final ProgressListener listener) { super(entity); this.listener = listener; } public static class CountingOutputStream extends FilterOutputStream { private final ProgressListener listener; private long transferred; CountingOutputStream(final OutputStream out, final ProgressListener listener) { super(out); this.listener = listener; this.transferred = 0; } @Override public void write(final byte[] b, final int off, final int len) throws IOException { out.write(b, off, len); this.transferred += len; this.listener.transferred(this.transferred); } @Override public void write(final int b) throws IOException { out.write(b); this.transferred++; this.listener.transferred(this.transferred); } } @Override public void writeTo(final OutputStream out) throws IOException { this.wrappedEntity.writeTo(out instanceof CountingOutputStream ? out : new CountingOutputStream(out, this.listener)); } /** * 进度监听器接口 */ public interface ProgressListener { public void transferred(long transferedBytes); } }
最后就是使用上述实现的类和Httpclient进行上传并显示进度的功能,非常简单,代码如下,使用AsyncTask异步上传。
/** * 异步AsyncTask+HttpClient上传文件,支持多文件上传,并显示上传进度 * @author JPH * Date:2014.10.09 * last modified 2014.11.03 */ public class UploadUtilsAsync extends AsyncTask<String, Integer, String>{ /**服务器路径**/ private String url; /**上传的参数**/ private Map<String,String>paramMap; /**要上传的文件**/ private ArrayList<File>files; private long totalSize; private Context context; private ProgressDialog progressDialog; public UploadUtilsAsync(Context context,String url,Map<String, String>paramMap,ArrayList<File>files) { this.context=context; this.url=url; this.paramMap=paramMap; this.files=files; } @Override protected void onPreExecute() {//执行前的初始化 // TODO Auto-generated method stub progressDialog=new ProgressDialog(context); progressDialog.setTitle("请稍等..."); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setCancelable(true); progressDialog.show(); super.onPreExecute(); } @Override protected String doInBackground(String... params) {//执行任务 // TODO Auto-generated method stub MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.setCharset(Charset.forName(HTTP.UTF_8));//设置请求的编码格式 builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);//设置浏览器兼容模式 int count=0; for (File file:files) { // FileBody fileBody = new FileBody(file);//把文件转换成流对象FileBody // builder.addPart("file"+count, fileBody); builder.addBinaryBody("file"+count, file); count++; } builder.addTextBody("method", paramMap.get("method"));//设置请求参数 builder.addTextBody("fileTypes", paramMap.get("fileTypes"));//设置请求参数 HttpEntity entity = builder.build();// 生成 HTTP POST 实体 totalSize = entity.getContentLength();//获取上传文件的大小 ProgressOutHttpEntity progressHttpEntity = new ProgressOutHttpEntity( entity, new ProgressListener() { @Override public void transferred(long transferedBytes) { publishProgress((int) (100 * transferedBytes / totalSize));//更新进度 } }); return uploadFile(url, progressHttpEntity); } @Override protected void onProgressUpdate(Integer... values) {//执行进度 // TODO Auto-generated method stub Log.i("info", "values:"+values[0]); progressDialog.setProgress((int)values[0]);//更新进度条 super.onProgressUpdate(values); } @Override protected void onPostExecute(String result) {//执行结果 // TODO Auto-generated method stub Log.i("info", result); Toast.makeText(context, result, Toast.LENGTH_LONG).show(); progressDialog.dismiss(); super.onPostExecute(result); } /** * 向服务器上传文件 * @param url * @param entity * @return */ public String uploadFile(String url, ProgressOutHttpEntity entity) { HttpClient httpClient=new DefaultHttpClient();// 开启一个客户端 HTTP 请求 httpClient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1); httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);// 设置连接超时时间 HttpPost httpPost = new HttpPost(url);//创建 HTTP POST 请求 httpPost.setEntity(entity); try { HttpResponse httpResponse = httpClient.execute(httpPost); if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { return "文件上传成功"; } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (ConnectTimeoutException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { if (httpClient != null && httpClient.getConnectionManager() != null) { httpClient.getConnectionManager().shutdown(); } } return "文件上传失败"; } }
关于服务器端如何接收:可以参考:《Android网络编程之使用HttpClient批量上传文件》,我在里面已经介绍的很清楚了。
如果你觉得这篇博文对你有帮助的话,请为这篇博文点个赞吧!也可以关注fengyuzhengfan的博客,收看更多精彩!http://blog.csdn.net/fengyuzhengfan/