http://blog.csdn.net/shinay/article/details/8472756
文章来自:http://toolongdidntread.com/android/android-multipart-post-with-progress-bar/
文件上传可能是一个比较耗时的操作,如果为上传操作带上进度提示则可以更好的提高用户体验,最后效果如下图:

项目源码:http://download.csdn.net/detail/shinay/4965230
这里只贴出代码,可根据实际情况自行修改。
-
package com.lxb.uploadwithprogress.http;
-
-
import java.io.File;
-
-
import org.apache.http.HttpResponse;
-
import org.apache.http.client.HttpClient;
-
import org.apache.http.client.methods.HttpPost;
-
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.HttpContext;
-
import org.apache.http.util.EntityUtils;
-
-
import android.app.ProgressDialog;
-
import android.content.Context;
-
import android.os.AsyncTask;
-
-
import com.lxb.uploadwithprogress.http.CustomMultipartEntity.ProgressListener;
-
-
public class HttpMultipartPost extends AsyncTask<String, Integer, String> {
-
-
private Context context;
-
private String filePath;
-
private ProgressDialog pd;
-
private long totalSize;
-
-
public HttpMultipartPost(Context context, String filePath) {
-
this.context = context;
-
this.filePath = filePath;
-
}
-
-
@Override
-
protected void onPreExecute() {
-
pd = new ProgressDialog(context);
-
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
-
pd.setMessage("Uploading Picture...");
-
pd.setCancelable(false);
-
pd.show();
-
}
-
-
@Override
-
protected String doInBackground(String... params) {
-
String serverResponse = null;
-
-
HttpClient httpClient = new DefaultHttpClient();
-
HttpContext httpContext = new BasicHttpContext();
-
HttpPost httpPost = new HttpPost("上传URL, 如:http://www.xx.com/upload.php");
-
-
try {
-
CustomMultipartEntity multipartContent = new CustomMultipartEntity(
-
new ProgressListener() {
-
@Override
-
public void transferred(long num) {
-
publishProgress((int) ((num / (float) totalSize) * 100));
-
}
-
});
-
-
-
multipartContent.addPart("data", new FileBody(new File(
-
filePath)));
-
totalSize = multipartContent.getContentLength();
-
-
-
httpPost.setEntity(multipartContent);
-
HttpResponse response = httpClient.execute(httpPost, httpContext);
-
serverResponse = EntityUtils.toString(response.getEntity());
-
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
-
return serverResponse;
-
}
-
-
@Override
-
protected void onProgressUpdate(Integer... progress) {
-
pd.setProgress((int) (progress[0]));
-
}
-
-
@Override
-
protected void onPostExecute(String result) {
-
System.out.println("result: " + result);
-
pd.dismiss();
-
}
-
-
@Override
-
protected void onCancelled() {
-
System.out.println("cancle");
-
}
-
-
}
-
package com.lxb.uploadwithprogress.http;
-
-
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(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);
-
}
-
}
-
-
}
上面为两个主要的类,下面放一个调用的Activity
-
package com.lxb.uploadwithprogress;
-
-
import java.io.File;
-
-
import com.lxb.uploadwithprogress.http.HttpMultipartPost;
-
-
import android.app.Activity;
-
import android.content.Context;
-
import android.os.Bundle;
-
import android.view.View;
-
import android.view.View.OnClickListener;
-
import android.widget.Button;
-
import android.widget.EditText;
-
import android.widget.Toast;
-
-
public class MainActivity extends Activity implements OnClickListener {
-
-
private Context context;
-
-
private EditText et_filepath;
-
private Button btn_upload;
-
private Button btn_cancle;
-
-
private HttpMultipartPost post;
-
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
-
context = this;
-
-
setContentView(R.layout.activity_main);
-
-
et_filepath = (EditText) findViewById(R.id.et_filepath);
-
btn_upload = (Button) findViewById(R.id.btn_upload);
-
btn_cancle = (Button) findViewById(R.id.btn_cancle);
-
-
btn_upload.setOnClickListener(this);
-
btn_cancle.setOnClickListener(this);
-
}
-
-
@Override
-
public void onClick(View v) {
-
switch (v.getId()) {
-
case R.id.btn_upload:
-
String filePath = et_filepath.getText().toString();
-
File file = new File(filePath);
-
if (file.exists()) {
-
post = new HttpMultipartPost(context, filePath);
-
post.execute();
-
} else {
-
Toast.makeText(context, "file not exists", Toast.LENGTH_LONG).show();
-
}
-
break;
-
case R.id.btn_cancle:
-
if (post != null) {
-
if (!post.isCancelled()) {
-
post.cancel(true);
-
}
-
}
-
break;
-
}
-
-
}
-
-
}
当然,在Android中使用MultipartEntity类,必须为项目增加相应的jar包,httpmime-4.1.2.jar。
最后放上代码,工程里已包含jar。
地址:
http://download.csdn.net/detail/shinay/4965230
Android 下载文件 进度条显示
http://blog.csdn.net/rwyz1314/article/details/6798222


加入两个权限
一个是联网,另一个是读写SD卡
-
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
下载地址是本人的另外一台主机,现在当服务器了,路径可以测试
http://210.30.12.1:8080/mp3/DJ.mp3
最近要实现一个检验更新的功能,当进入程序的时候,开始请求服务器,然后得到服务器的响应更新结果!如果需要更新的话,就打开一个Dialog,在Dialog上面下载文件,于是自己研究了一个自定义dialog的实现,也完成了在dialog上面有进度的下载文件(自己的作图技术查,随便画了一个背景
),效果图如下:


效果如上,下面我把代码贴出来:
主界面Activity: 主界面就定义了一个Button,当点击Button后,弹出Dialog
-
package com.spring.sky.dialog.download;
-
-
-
import android.app.Activity;
-
import android.os.Bundle;
-
import android.view.View;
-
import android.widget.Button;
-
import android.widget.ImageView;
-
-
/**
-
* 主界面
-
* @author spring sky
-
*/
-
public class MainActivity extends Activity implements
-
android.view.View.OnClickListener {
-
private Button bt;
-
private ImageView imageView;
-
-
@Override
-
public void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.main);
-
init();
-
}
-
-
private void init() {
-
bt = (Button) this.findViewById(R.id.bt);
-
bt.setOnClickListener(this);
-
imageView = (ImageView) findViewById(R.id.imageview);
-
}
-
-
@Override
-
public void onClick(View v) {
-
DownloadDialog dialog = new DownloadDialog(this,
-
"http://img308.ph.126.net/AM2zg9CNx0kG8K3jY122RQ==/3902932027070067384.jpg");
-
dialog.setImageView(imageView); //当前下载的是一个图片,所以下载完成后,把这个图片显示在界面上
-
dialog.show();
-
}
-
}
main.xml:
-
<?xml version="1.0" encoding="utf-8"?>
-
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
-
android:layout_width="fill_parent"
-
android:layout_height="fill_parent"
-
android:orientation="vertical" >
-
-
<LinearLayout
-
android:layout_width="fill_parent"
-
android:layout_height="fill_parent"
-
android:orientation="vertical" >
-
-
<Button
-
android:id="@+id/bt"
-
android:layout_width="fill_parent"
-
android:layout_height="wrap_content"
-
android:text="弹出框下载文件" />
-
-
<ImageView
-
android:id="@+id/imageview"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:layout_gravity="center_vertical"
-
/>
-
</LinearLayout>
-
-
</ScrollView>
自定义的Dialog : 这个基本就是实现Dialog的布局,还有Dialog的背景透明效果,然后用户点击了下载,启动一个新线程下载,同时用handler来发送消息,让下载操作的进度在Dialog的view上面呈现出来,当下载完成的时候,点击按钮就可以看见下载的图片了! (我测试为了简单就用了一个ImageView把图片显示出来)
-
package com.spring.sky.dialog.download;
-
-
import java.io.FileOutputStream;
-
import java.io.InputStream;
-
import java.net.URL;
-
import java.net.URLConnection;
-
-
-
import android.app.Dialog;
-
import android.content.Context;
-
import android.graphics.BitmapFactory;
-
import android.os.Bundle;
-
import android.os.Handler;
-
import android.os.Message;
-
import android.util.Log;
-
import android.view.View;
-
import android.widget.Button;
-
import android.widget.ImageView;
-
import android.widget.ProgressBar;
-
import android.widget.TextView;
-
import android.widget.Toast;
-
-
-
-
-
-
-
public class DownloadDialog extends Dialog implements
-
android.view.View.OnClickListener {
-
private static final int DOWNLOAD_PREPARE = 0;
-
private static final int DOWNLOAD_WORK = 1;
-
private static final int DOWNLOAD_OK = 2;
-
private static final int DOWNLOAD_ERROR = 3;
-
private static final String TAG = "IndexActivity";
-
private Context mContext;
-
-
private Button bt;
-
private ProgressBar pb;
-
-
private boolean isClick = false;
-
private boolean downloadOk = false;
-
private TextView tv;
-
-
-
-
private String url = null;
-
private String filePath;
-
-
-
-
-
int fileSize = 0;
-
-
-
-
-
int downloadSize = 0;
-
-
-
-
-
private Handler handler = new Handler() {
-
-
@Override
-
public void handleMessage(Message msg) {
-
switch (msg.what) {
-
case DOWNLOAD_PREPARE:
-
Toast.makeText(mContext, "准备下载", Toast.LENGTH_SHORT).show();
-
pb.setVisibility(ProgressBar.VISIBLE);
-
Log.e(TAG, "文件大小:" + fileSize);
-
pb.setMax(fileSize);
-
break;
-
case DOWNLOAD_WORK:
-
Log.e(TAG, "已经下载:" + downloadSize);
-
pb.setProgress(downloadSize);
-
int res = downloadSize * 100 / fileSize;
-
tv.setText("已下载:" + res + "%");
-
bt.setText(FileUtil.FormetFileSize(downloadSize) + "/"
-
+ FileUtil.FormetFileSize(fileSize));
-
break;
-
case DOWNLOAD_OK:
-
downloadOk = true;
-
bt.setText("下载完成显示图片");
-
downloadSize = 0;
-
fileSize = 0;
-
Toast.makeText(mContext, "下载成功", Toast.LENGTH_SHORT).show();
-
break;
-
case DOWNLOAD_ERROR:
-
downloadSize = 0;
-
fileSize = 0;
-
Toast.makeText(mContext, "下载失败", Toast.LENGTH_SHORT).show();
-
break;
-
}
-
super.handleMessage(msg);
-
}
-
};
-
-
private ImageView imageView;
-
-
public DownloadDialog(Context context, String url) {
-
-
super(context, R.style.Theme_CustomDialog);
-
mContext = context;
-
this.url = url;
-
filePath = FileUtil.getPath(mContext, url);
-
}
-
-
@Override
-
public void cancel() {
-
super.cancel();
-
}
-
-
-
-
-
private void downloadFile() {
-
try {
-
URL u = new URL(url);
-
URLConnection conn = u.openConnection();
-
InputStream is = conn.getInputStream();
-
fileSize = conn.getContentLength();
-
if (fileSize < 1 || is == null) {
-
sendMessage(DOWNLOAD_ERROR);
-
} else {
-
sendMessage(DOWNLOAD_PREPARE);
-
FileOutputStream fos = new FileOutputStream(filePath);
-
byte[] bytes = new byte[1024];
-
int len = -1;
-
while ((len = is.read(bytes)) != -1) {
-
fos.write(bytes, 0, len);
-
fos.flush();
-
downloadSize += len;
-
sendMessage(DOWNLOAD_WORK);
-
}
-
sendMessage(DOWNLOAD_OK);
-
is.close();
-
fos.close();
-
}
-
} catch (Exception e) {
-
sendMessage(DOWNLOAD_ERROR);
-
e.printStackTrace();
-
}
-
}
-
-
-
-
-
-
public String getFilePath() {
-
return filePath;
-
}
-
private void init() {
-
bt = (Button) this.findViewById(R.id.down_bt);
-
bt.setOnClickListener(this);
-
tv = (TextView) this.findViewById(R.id.down_tv);
-
pb = (ProgressBar) this.findViewById(R.id.down_pb);
-
}
-
-
@Override
-
public void onClick(View v) {
-
switch (v.getId()) {
-
case R.id.down_bt:
-
if (isClick) {
-
-
Thread thread = new Thread(new Runnable() {
-
@Override
-
public void run() {
-
downloadFile();
-
}
-
});
-
thread.start();
-
isClick = false;
-
}
-
-
if (downloadOk)
-
{
-
imageView.setImageBitmap(BitmapFactory.decodeFile(filePath));
-
cancel();
-
}
-
break;
-
default:
-
break;
-
}
-
}
-
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.download_layuot);
-
init();
-
}
-
-
-
-
-
private void sendMessage(int what) {
-
Message m = new Message();
-
m.what = what;
-
handler.sendMessage(m);
-
}
-
-
public void setImageView(ImageView imageView) {
-
this.imageView = imageView;
-
}
-
-
@Override
-
public void show() {
-
isClick = true;
-
downloadOk = false;
-
super.show();
-
}
-
-
}
dialog的download_layuot.xml布局文件: 这个使用了相对布局,让ProgressBar和TextView呈现在一个居中位置,看起来就像连在一起的效果!同时Button来实现文件大小的显示
-
<?xml version="1.0" encoding="utf-8"?>
-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:background="@drawable/dialog"
-
android:orientation="vertical" >
-
<TextView
-
android:layout_margin="5dip"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:layout_gravity="center_horizontal"
-
android:text="有新的版本更新"
-
android:textSize="20dip"
-
android:textColor="@android:color/white" />
-
-
<RelativeLayout
-
android:layout_margin="10dip"
-
android:layout_width="fill_parent"
-
android:layout_height="wrap_content"
-
android:layout_gravity="center_horizontal"
-
>
-
<ProgressBar
-
android:layout_centerHorizontal="true"
-
android:layout_centerVertical="true"
-
android:id="@+id/down_pb"
-
style="?android:attr/progressBarStyleHorizontal"
-
android:layout_width="260dip"
-
android:layout_height="wrap_content"
-
/>
-
<TextView
-
android:layout_centerHorizontal="true"
-
android:layout_centerVertical="true"
-
android:id="@+id/down_tv"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content"
-
android:text="开始下载..."
-
android:textColor="@android:color/white"
-
android:textSize="20sp" />
-
</RelativeLayout>
-
<Button
-
android:layout_gravity="center_horizontal"
-
android:id="@+id/down_bt"
-
android:layout_width="wrap_content"
-
android:layout_height="fill_parent"
-
android:text="点击下载"
-
android:textColor="@android:color/black"
-
android:textSize="16sp"
-
android:layout_marginTop="10dip"
-
android:layout_marginBottom="10dip" />
-
</LinearLayout>
在dialog中需要一个样式,这个样式可以实现Dialog后面的背景透明:
-
<?xml version="1.0" encoding="utf-8"?>
-
-
<shape xmlns:android="http://schemas.android.com/apk/res/android">
-
<stroke android:width="3dp"/>
-
<corners android:radius="3dp" />
-
<padding android:left="10dp" android:top="10dp"
-
android:right="10dp" android:bottom="10dp" />
-
<solid android:color="@android:color/transparent"/>
-
</shape>
还有一个FileUtil.java的文件工具类: