<span style="font-size:14px;">算起来最近的项目应用情形,在文件上传的时候,应用HttpClient上传文件,我们总是在上传完成前使用一个进度条(一直转圈似的)来显示用户等待的过程,对于用户体验度来说这是相当不好的,大多数情况我们需要有一个详细的进度展示给用户,让用户可以知道实际的进度。刚好下发的任务要求这次项目版本升级需要加入这个功能,结合<a target=_blank href="http://toolongdidntread.com/android/android-multipart-post-with-progress-bar/" style="box-sizing: border-box; border: 0px; font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(210, 83, 73); text-decoration: none; -webkit-transition: all 0.3s ease-in-out; line-height: 28.78333282470703px; background-color: rgb(233, 231, 227); ">http://toolongdidntread.com/android/android-multipart-post-with-progress-bar/</a>我将其修改,作为独立的jar文件(因为依赖异步任务类,所以该jar文件只能应用于android,如果需要用于普通java应用,需要将源码中的异步任务改为开启新线程)取出来,同时提供两个回调接口:进度、服务器返回消息;</span>
package com.ilovn.libs.fileupload;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
public class CustomMultiPartEntity extends MultipartEntity {
private final ProgressListener listener;
public CustomMultiPartEntity(final ProgressListener listener) {
super();
this.listener = listener;
}
public CustomMultiPartEntity(final HttpMultipartMode mode,
final ProgressListener listener) {
super(mode);
this.listener = listener;
}
public CustomMultiPartEntity(HttpMultipartMode mode, final String boundary,
final Charset charset, final ProgressListener listener) {
super(mode, boundary, charset);
this.listener = listener;
}
@Override
public void writeTo(final OutputStream outstream) throws IOException {
super.writeTo(new CountingOutputStream(outstream, this.listener));
}
public static interface ProgressListener {
void transferred(long num);
}
public static class CountingOutputStream extends FilterOutputStream {
private final ProgressListener listener;
private long transferred;
public CountingOutputStream(final OutputStream out,
final ProgressListener listener) {
super(out);
this.listener = listener;
this.transferred = 0;
}
public void write(byte[] b, int off, int len) throws IOException {
out.write(b, off, len);
this.transferred += len;
this.listener.transferred(this.transferred);
}
public void write(int b) throws IOException {
out.write(b);
this.transferred++;
this.listener.transferred(this.transferred);
}
}
}
package com.ilovn.libs.fileupload;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.FormBodyPart;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import android.os.AsyncTask;
import android.util.Log;
import android.webkit.URLUtil;
import com.ilovn.libs.fileupload.CustomMultiPartEntity.ProgressListener;
/**
* 文件上传
*
* @author zhaoyong
*
*/
public class HttpMultipartPost extends AsyncTask<HttpResponse, Integer, String> {
private static final String TAG = HttpMultipartPost.class.getSimpleName();
private String url;
private long totalSize;
private String[] files;
private FormBodyPart[] parts;
private CallBack mCallBack;
private CallBackMsg mCallBackMsg;
private String encode = HTTP.UTF_8;
/**
*
* @param url
* @param files
* 文件路径
* @param parts
* 其他参数
* @param fileEncode 编码 默认UTF-8
*
*/
public HttpMultipartPost(String url, String[] files, String fileEncode,
FormBodyPart... parts) {
super();
this.url = url;
this.files = files;
this.parts = parts;
this.encode = StringUtils.isEmpty(fileEncode) ? HTTP.UTF_8 : fileEncode;
}
@Override
protected void onPreExecute() {
if (!URLUtil.isNetworkUrl(url)) {
throw new IllegalArgumentException("unvalid url for post!");
}
}
@Override
protected String doInBackground(HttpResponse... arg0) {
HttpClient httpClient = new DefaultHttpClient();
HttpContext httpContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(url);
try {
CustomMultiPartEntity multipartContent = new CustomMultiPartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE, null,
Charset.forName(encode), new ProgressListener() {
@Override
public void transferred(long num) {
publishProgress((int) ((num / (float) totalSize) * 100));
}
});
// add all file
for (String file : files) {
multipartContent.addPart("files", new FileBody(new File(file)));
}
// add other parts
for (FormBodyPart part : parts) {
multipartContent.addPart(part);
}
totalSize = multipartContent.getContentLength();
// Send it
httpPost.setEntity(multipartContent);
HttpResponse response = httpClient.execute(httpPost, httpContext);
String serverResponse = EntityUtils.toString(response.getEntity());
return serverResponse;
} catch (IOException e) {
return "{\"msg\":\"post failed!\"}";
}
}
@Override
protected void onProgressUpdate(Integer... progress) {
if (mCallBack != null) {
mCallBack.update(progress[0]);
}
}
@Override
protected void onPostExecute(String param) {
Log.d(TAG, param + "");
if (mCallBackMsg != null) {
mCallBackMsg.msg(param);
}
}
public void setCallBack(CallBack mCallBack) {
this.mCallBack = mCallBack;
}
public void setCallBackMsg(CallBackMsg mCallBackMsg) {
this.mCallBackMsg = mCallBackMsg;
}
public interface CallBack {
public void update(Integer i);
}
public interface CallBackMsg {
public void msg(String msg);
}
}
DEMO效果图:
![DEMO效果图 DEMO效果图](http://ilovn.com/uploads/2012/09/2000.jpg)
转自:http://www.ilovn.com/topic/upload-android-with-feedback-on-the-progress-of-implementation/