多线程断点续传及下载
断点下载
package com.example.downloaddemo;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MoreThreadDownActivity extends Activity implements OnClickListener{
private Button start_download1;
/** 显示下载进度TextView */
private TextView download_info1;
int fileSize;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_more_thread_down);
start_download1 = (Button) findViewById(R.id.start_download1);
download_info1 = (TextView) findViewById(R.id.download_info1);
start_download1.setOnClickListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_more_thread_down, menu);
return true;
}
//点击下载按钮,开始下载
@Override
public void onClick(View v) {
doDownload();//调用下载的函数
}
/**
* 使用Handler更新UI界面信息
*/
@SuppressLint("HandlerLeak")
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// mProgressbar.setProgress();
//
float temp = (float) msg.getData().getInt("size")
/ (float) fileSize;
//
int progress = (int) (temp * 100);
Log.i("TAG", "当前进度:"+progress);
// if (progress == 100) {
// Toast.makeText(MainApp.this, "下载完成!", Toast.LENGTH_LONG).show();
// }
download_info1.setText("下载进度:" + progress + "%");
}
};
/**
* 下载准备工作,获取SD卡路径、开启线程
*/
private void doDownload() {
download_info1.setText("开始下载");
// 获取SD卡路径
String path = "/sdcard/" + System.currentTimeMillis() + "acedownload.mp4";
String downloadUrl = "http://101.200.142.201:8080/tqyb/ace.mp4";
File file = new File(path);
// 如果SD卡目录不存在创建
// if (!file.exists()) {
// file.mkdir();
// }
// 简单起见,我先把URL和文件名称写死,其实这些都可以通过HttpHeader获取到
int threadNum = 5;
Log.d("TAG", "download file path:" + path);
DownloadTask task = new DownloadTask(downloadUrl, threadNum, path);
task.start();
}
private static final String TAG = "TAG";
/**
* 多线程文件下载
*
* @author yangxiaolong
* @2014-8-7
*/
class DownloadTask extends Thread {
private String downloadUrl;// 下载链接地址
private int threadNum;// 开启的线程数
private String filePath;// 保存文件路径地址
private int blockSize;// 每一个线程的下载量
public DownloadTask(String downloadUrl, int threadNum, String fileptah) {
this.downloadUrl = downloadUrl;
this.threadNum = threadNum;
this.filePath = fileptah;
}
@Override
public void run() {
//创建下载线程的数组,长度为5
FileDownloadThread[] threads = new FileDownloadThread[threadNum];
try {
URL url = new URL(downloadUrl); //创建下载需要的网络请求对象 URL的对象
Log.d(TAG, "download file http path:" + downloadUrl);
URLConnection conn = url.openConnection();//创建 网络请求的URLConnection
// 读取下载文件总大小
fileSize = conn.getContentLength();
if (fileSize <= 0) {
System.out.println("读取文件失败");
return;
}
// 计算每条线程下载的数据长度
blockSize = (fileSize % threadNum) == 0 ? fileSize / threadNum : fileSize / threadNum + 1;
Log.d(TAG, "fileSize:" + fileSize + " blockSize:");
//下载的文件,存放的位置
File file = new File(filePath);
//启动5条线程,同时下载
for (int i = 0; i < threads.length; i++) {
// 启动线程,分别下载每个线程需要下载的部分
threads[i] = new FileDownloadThread(url, file, blockSize, (i + 1));
threads[i].setName("Thread:" + i);
threads[i].start();
}
//上面的5条线程,启动后,自己执行自己的,下面的代码也同时执行,不受影响
boolean isfinished = false;
int downloadedAllSize = 0;
while (!isfinished) { //循环判断,5个线程的总体下载进度,已经是否每个都完成了
isfinished = true;
// 当前所有线程下载总量
downloadedAllSize = 0;
for (int i = 0; i < threads.length; i++) {
downloadedAllSize += threads[i].getDownloadLength();
if (!threads[i].isCompleted()) {
isfinished = false;
}
}
// 通知handler去更新视图组件
Message msg = new Message();
msg.getData().putInt("size", downloadedAllSize);
mHandler.sendMessage(msg);
// Log.d(TAG, "current downloadSize:" + downloadedAllSize);
Thread.sleep(1000);// 休息1秒后再读取下载进度
}
Log.d(TAG, " all of downloadSize:" + downloadedAllSize);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.example.downloaddemo;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection;
import android.util.Log;
/**
* 文件下载类
*
* @author
* @2014-5-6
*/
public class FileDownloadThread extends Thread {
private static final String TAG = FileDownloadThread.class.getSimpleName();
/** 当前下载是否完成 */
private boolean isCompleted = false;
/** 当前下载文件长度 */
private int downloadLength = 0;
/** 文件保存路径 */
private File file;
/** 文件下载路径 */
private URL downloadUrl;
/** 当前下载线程ID */
private int threadId;
/** 线程下载数据长度 */
private int blockSize;
/**
*
* @param url:文件下载地址
* @param file:文件保存路径
* @param blocksize:下载数据长度
* @param threadId:线程ID
*/
public FileDownloadThread(URL downloadUrl, File file, int blocksize, int threadId) {
this.downloadUrl = downloadUrl;
this.file = file;
this.threadId = threadId;
this.blockSize = blocksize;
}
@Override
public void run() {
BufferedInputStream bis = null;
RandomAccessFile raf = null;
try {
URLConnection conn = downloadUrl.openConnection();
conn.setAllowUserInteraction(true);
int startPos = blockSize * (threadId - 1);//开始位置
int endPos = blockSize * threadId - 1;//结束位置
//设置当前线程下载的起点、终点 bytes=4-7
conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos);
System.out.println(Thread.currentThread().getName() + " bytes="
+ startPos + "-" + endPos);
byte[] buffer = new byte[1024];
bis = new BufferedInputStream(conn.getInputStream());
raf = new RandomAccessFile(file, "rwd"); //创建随机读写流,从本线程下载的位置作为写的位置,把下载的数据写入文件
raf.seek(startPos); //设置写的位置
int len;
while ((len = bis.read(buffer, 0, 1024)) != -1) { //循环读取本次线程下载的数据,写入文件
raf.write(buffer, 0, len);
downloadLength += len; //记录读取的数据的数量,显示在进度条上
}
isCompleted = true; //循环走完了,说明本线程下载完了
Log.d(TAG, "current thread task has finished,all size:"
+ downloadLength);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (raf != null) {
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 线程文件是否下载完毕
*/
public boolean isCompleted() {
return isCompleted;
}
/**
* 线程下载文件长度
*/
public int getDownloadLength() {
return downloadLength;
}
}
断点续传
package com.example.uptoserverdemo;
import java.io.File;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.*;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import com.lidroid.xutils.ViewUtils;
import com.lidroid.xutils.view.annotation.event.OnClick;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView tv;
public static final String UP_URL = "http://169.254.109.73:8080/upserver/UploadFileServlet";
// private String filePath = "/storage/sdcard0/1461656337024acedownload.mp4";
// String fileName = "1461656337024acedownload.mp4";
private String filePath = "/mnt/sdcard/ace.mp4";
String fileName = "ace.mp4";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
ViewUtils.inject(this);
}
@OnClick(R.id.tv)
public void jump(View view){
//异步上传文件
new MyAsyncTask().execute();
}
class MyAsyncTask extends AsyncTask<String, Integer, String>{
@Override
protected String doInBackground(String... params) {
String rs = "";
String httpUrl = UP_URL+"?fileName="+fileName;
HttpPost request = new HttpPost(httpUrl);
File file = new File(filePath);
//上传文件的配置代码
FileEntity entity = new FileEntity(file,"binary/octet-stream");
entity.setContentEncoding("binary/octet-stream");
request.setEntity(entity);
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response;
try {
response = httpClient.execute(request);
//如果返回状态为200,获得返回的结果
if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
//图片上传成功
Log.i("TAG","上传成功");
HttpEntity rsEntity = response.getEntity();
rs = EntityUtils.toString(rsEntity, "utf-8");
Log.i("TAG",rs);
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rs;
}
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
tv.setText(result);
}
}
}