您的位置:首页 > 其它

实现多线程断点下载可以运行

2016-10-25 07:12 295 查看
//1.首先获取下载文件的总大小
//2.然后确定其要下载的线程数量
//3.根据数量来确定开始位置及结束位置
//4.要进行断点下载必须要把下载的保存到文件中
public class DownLoad {
private String filePath;
private ProgressBar progressBar;
private int currentProgress;
private String path;
private long rate;

public DownLoad(ProgressBar progressBar) {
this.progressBar = progressBar;
this.progressBar.setMax(100);
String tempPath = Environment.getExternalStorageDirectory() + "/DownLoad";
File file = new File(tempPath);
if (!file.exists())
file.mkdir();
filePath = tempPath + "/gg.apk";
}

public void loadData(String path) {
this.currentProgress = 0;
this.path = path;
try {
URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(4000);
if (connection.getResponseCode() == 200) {
long length = connection.getContentLength();
rate = length / 100;
File file = new File(filePath);
if(!file.exists()) {//如何文件不存在就创建一个空洞文件
RandomAccessFile raf = new RandomAccessFile(filePath, "rwd");
raf.setLength(length);
raf.close();
}

long eachLen = length / 3;
for (int i = 0; i < 3; i++) {
int endindex = (int) ((i+1)*eachLen);
if (i == 2) {
endindex = (int) length;
}
new MyThread(i,i*eachLen,endindex).start();
}
}

} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

private class MyThread extends Thread {
private long begainIndex;
private long endIndex;
private int threadId;

public MyThread(int threadId, long begainIndex, long endIndex) {
this.threadId = threadId;
this.begainIndex = begainIndex;
this.endIndex = endIndex;
}

@Override
public void run() {

RandomAccessFile raf = null;
try {
URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//从本地读取出进度
getDateFromTempFile();

connection.setRequestProperty("Range", "bytes=" + begainIndex + "-" + endIndex);
connection.setConnectTimeout(5000);

int resultCode = connection.getResponseCode();
if (resultCode == 200 || resultCode == 206) {
InputStream is = connection.getInputStream();
raf = new RandomAccessFile(filePath, "rwd");
raf.seek(begainIndex);

int len = 0,total=0;
byte[] bufs = new byte[2048*5];
while ((len = (is.read(bufs))) != -1) {
total+=len;
raf.write(bufs, 0, len);
saveCountTempFile(total);
updateProgress(len);
}

Log.e("===","下载完成");

deleteTempCountFile();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (raf == null) {
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

}

//从临时文件中获取数据来接着下载
private void getDateFromTempFile() throws IOException {
File file = new File(Environment.getExternalStorageDirectory()+"/"+threadId+".txt");
//如果这样的文件不存在就结束
if(!file.exists())
return;

ObjectInputStream obs = new ObjectInputStream(new FileInputStream(Environment.getExternalStorageDirectory()+"/"+threadId+".txt"));
int tempLen = obs.readInt()-1;
Log.e("===",threadId+":"+tempLen);

begainIndex+=tempLen;
currentProgress+=tempLen;
obs.close();
}

//保存临时文件
private void saveCountTempFile(int total) throws IOException {
ObjectOutputStream obs = new ObjectOutputStream(new FileOutputStream(Environment.getExternalStorageDirectory()+"/"+threadId+".txt"));
obs.writeInt(total);
obs.close();
}

//更新进度条
private void updateProgress(int len) {
synchronized (DownLoad.this) {
currentProgress += len;
int tempProgress = (int) (currentProgress/rate);
progressBar.setProgress(tempProgress);
}
}

//删除临时文件
private void deleteTempCountFile() {
File file = new File(Environment.getExternalStorageDirectory()+"/"+threadId+".txt");
if(file.exists())
file.delete();
}
}
}

补充:
1.如何判断他是否下载完成?我们可以在外部类中定义一个变量记录下载完成数当一个线程下载完成就把它加1并判断它的大小是否与总
线程数相同吗,如果相同就表示下载完成。
2,对于用了存放每个线程下载的长度我使用的是下载一点就在文件中记录并关闭它,下次又开启效率有点底。
3,对于下载开始前我先是判断它是否存在临时文件如果不存在表示第一次开始下载,如果存在表示时接着下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: