Android网络编程之使用HttpClient批量上传文件(二)AsyncTask+HttpClient并实现上传进度监听

请尊重他人的劳动成果,转载请注明出处:

Android网络编程之使用HttpClient批量上传文件(二)AsyncTask+HttpClient并实现上传进度监听

运行效果图:

我曾在《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/

时间: 2024-10-10 02:23:14

Android网络编程之使用HttpClient批量上传文件(二)AsyncTask+HttpClient并实现上传进度监听的相关文章

Android网络编程之使用HttpClient批量上传文件

请尊重他人的劳动成果,转载请注明出处:Android网络编程之使用HttpClient批量上传文件 我曾在<Android网络编程之使用HTTP访问网络资源>一文中介绍过HttpCient的使用,这里就不在累述了,感兴趣的朋友可以去看一下.在这里主要介绍如何通过HttpClient实现文件上传. 1.预备知识: 在HttpCient4.3之前上传文件主要使用MultipartEntity这个类,但现在这个类已经不在推荐使用了.随之替代它的类是MultipartEntityBuilder. 下面

转 Android网络编程之使用HttpClient批量上传文件 MultipartEntityBuilder

请尊重他人的劳动成果,转载请注明出处:Android网络编程之使用HttpClient批量上传文件 http://www.tuicool.com/articles/Y7reYb 我曾在<Android网络编程之使用HTTP访问网络资源>一文中介绍过HttpCient的使用,这里就不在累述了,感兴趣的朋友可以去看一下.在这里主要介绍如何通过HttpClient实现文件上传. 1.预备知识: 在HttpCient4.3之前上传文件主要使用MultipartEntity这个类,但现在这个类已经不在推

Android网络编程(二)HttpClient与HttpURLConnection

相关文章 Android网络编程(一)HTTP协议原理 前言 上一篇我们了解了HTTP协议原理,这一篇我们来讲讲Apache的HttpClient和Java的HttpURLConnection,这两种都是我们平常请求网络会用到的.无论我们是自己封装的网络请求类还是第三方的网络请求框架都离不开这两个类库. 1.HttpClient Android SDK中包含了HttpClient,在Android6.0版本直接删除了HttpClient类库,如果仍想使用则解决方法是: 如果使用的是eclipse

Android网络编程之获取网络上的XML

Android网络编程之获取网络上的XML 请尊重他人的劳动成果,转载请注明出处:Android网络编程之获取网络上的XML 为要获取网络上的XML所以需要服务器端提供的支持. 一.创建服务器端: 服务器端项目结构: 服务器端运行效果图: 第一步:创建业务所需的JavaBean package com.jph.server.model; import java.util.Date; /** * 新闻实体类 * @author jph * Date:2014.09.26 */ public cla

Android网络编程之获取网络上的Json

Android网络编程之获取网络上的Json 请尊重他人的劳动成果,转载请注明出处:Android网络编程之获取网络上的Json 为要获取网络上的Json所以需要服务器端提供的支持. 一.创建服务器端: 服务器端项目结构: 服务器端运行效果图: 第一步:创建业务所需的JavaBean package com.jph.sj.model; import java.util.Date; /** * 新闻实体类 * @author jph * Date:2014.09.26 */ public clas

Android 网络编程之---HttpClient 与 HttpURLConnection 共用cookie

前言 在编程过程中总结归纳出来的一种编程经验,从而形成的设计思想称为设计模式. 设计模式有23种.它适用于所有的编程语言. 常用的有创新型的设计模式:简单工厂.抽象工厂和单例模式:行为型的设计模式:模板设计模式.观察者模式和命令模式:结构性的设计模式:适配器设计模式.代理模式(静态和动态两种,典型的有在spring的AOP编程中使用)和装饰器设计模式. 正文 单例模式(singleton) 保证一个类在内存中只能创建一个实例. 1.实现步骤: 1)将构造器私有化,即使用private修饰构造器

Android网络开源库-Retrofit(三) 批量上传及上传进度监听

由于gif图太大的原因,我将图放在了github,如果博客中显示不出来图,传送门 由于我是事先写在md上的,导致代码的可读性差,大家将就着看吧. 1. 前言 在上一篇博客中,我们介绍了Retrofit的文件上传,文件下载以及进度监听,这篇博客我们来了解下批量上传以及上传进度的监听. 2.批量上传 要想实现批量上传,我们要考虑下HTML中实现批量上传的方法,借助Form表单,所以,我们也可以通过借助Form表单来实现批量上传. 2.1 HTML FORM 表单的写法 <html> <bod

Android网络编程网上文章总结

关于网络编程,网上也有许多好的文章,这里我就选了几篇觉得不错的归纳到了一起,仅供参考 Android网络编程概述 首先,应该了解的几个问题: 1)Android平台网络相关API接口 a) java.net.*(标准Java接口) java.net.*提供与联网有关的类,包括流.数据包套接字(socket).Internet协议.常见Http处理等.比如:创建URL,以及URLConnection/HttpURLConnection对象.设置链接参数.链接到服务器.向服务器写数据.从服务器读取数

Android网络编程系列 一 TCP/IP协议族

在学习和使用Android网路编程时,我们接触的仅仅是上层协议和接口如Apache的httpclient或者Android自带的httpURlconnection等等.对于这些接口的底层实现我们也有必要进一步的了解,这就要我们了解网络通信层了,提到网络通信层不得不说起ISO-OSI的七层协议经典架构,如图所示: 上图的左边部分就是osi架构模型了, ISO/OSI模型,即开放式通信系统互联参考模型(Open System Interconnection Reference Model),是国际标