您的位置:首页 > 编程语言 > Java开发

java多线程断点续传下载

2015-11-15 12:05 363 查看
断点续传就是利用临时文件,在下载的时候把每个线程下载的进度存到一个进度文件里,等下次再下载的时候直接从进度文件里读取这个值,然后+上开始时候的值继续下载就可以了

package down;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

public class Down {

static int threadCount = 3;
//记录完成下载线程的个数
static int finishThread = 0;
static String path = "http://192.168.21.1:8080/ok/TGPSetup.exe";

/**
* @param args
*/
public static void main(String[] args) {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(5000);
conn.setConnectTimeout(5000);
if (conn.getResponseCode() == 200) {
// 第一次请求要下载的长度
int length = conn.getContentLength();
// 应该从字符串中截取文件名称
File file = new File("TGPSetup.exe");
// 在下载之前生成临时文件,占位置
RandomAccessFile rdm = new RandomAccessFile(file, "rwd");
// 给临时文件大小
rdm.setLength(length);
// 关闭
rdm.close();
// 计算每个线程应该下载的长度
int size = length / threadCount;
// 为每个线程分配开始位置和结束位置
for (int i = 0; i < threadCount; i++) {
int start = i * size;
int end = (i + 1) * size - 1;
// 最后一个线程的结束位置为总长度
if (i == threadCount - 1) {
end = length;
}
// 每次都调用新的线程
new DownThread(start, end, i).start();
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

// 线程
class DownThread extends Thread {
private int start;
private int end;
private int threadId;

public DownThread(int start, int end, int threadId) {
this.start = start;
this.end = end;
this.threadId = threadId;
}

@Override
public void run() {
try {
//创建进度文件
File progressFile = new File(threadId + ".txt");
//判断是否有记录进度的文件,如果有的话把开始位置重新赋值
if (progressFile.exists()) {
FileInputStream fis = new FileInputStream(progressFile);
BufferedReader br = new BufferedReader(new InputStreamReader(
fis));
start+=Integer.parseInt(br.readLine());
fis.close();

}
System.out.println(threadId + "线程下载区间" + start + "---" + end);
// 再次请求网络
URL url = new URL(Down.path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(5000);
conn.setConnectTimeout(5000);
// 设置本次请求的文件的长度
conn.setRequestProperty("Range", "bytes=" + start + "-" + end);
// 请求部分数据是206
if (conn.getResponseCode() == 206) {
// 得到请求长度的文件输入流
InputStream is = conn.getInputStream();
byte[] b = new byte[1024];
int len = 0;
// 记录每一次下载字节数
int totle = 0;
// 应该从字符串中截取文件名称
File file = new File("TGPSetup.exe");
// 拿到之前占位置那个文件,相当于输出流
RandomAccessFile rdm = new RandomAccessFile(file, "rwd");
// 改变写入文件的开始位置
rdm.seek(start);
while ((len = is.read(b)) != -1) {
// 每次读取流里的数据写到临时文件里
rdm.write(b, 0, len);
totle += len;
//System.out.println(threadId + "线程" + "下载了" + totle);
//把下载的总数存到进度文件里
RandomAccessFile rdm1 = new RandomAccessFile(progressFile,
"rwd");
rdm1.write((totle + "").getBytes());
rdm1.close();
}
rdm.close();
Down.finishThread++;
//下载结束删除进度文件
if(Down.finishThread==Down.threadCount){
//加同步锁
synchronized (Down.path) {
for (int i = 0; i < Down.threadCount; i++) {
File f = new File(i+".txt");
f.delete();
}
Down.finishThread = 0;
}
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: