多线程断点下载:顾名思义是用多线程实现的,断点是当第三方因素(断电、断网等)中断下载时,下次下载可以继续上次下载的地方下载。
1、通过getContentLength可以获取要下载文件的大小,这样可以在本机上创建一个相同大小的文件用来下载。
int fileLength = connection.getContentLength();
2、由于是多线程,所以要给每一个线程均分分配要下载的位置。
for(int i = 0; i < threadCount; i ++) {int startThread = i *blockSize;int endThread = (i + 1) * blockSize - 1;if( i == blockSize - 1) endThread = fileLength -1;newDownloadThread(i, startThread, endThread).start();
}
3、启动每个线程下载时,请求头需要Range参数,值是bytes:xxx-xxx某事。比如"Range:0-10100",代表要下载的位置是从0到10100。
connection.setRequestProperty("Range", "bytes:"+startThred+"-" + endThread);
4、然后每次用RandomAccessFile写入数据到本机文件里。
while((length = inputStream.read(buffer)) != -1) {
randomAccessFile.write(buffer,0, length);
}
5、当然每次下载时需要记录本线程下载了多少,以便断点时,下载的时候可以从下次下载的地方下载。
total +=length;int currentThreadPostion = startThred +total;
RandomAccessFile randomAccessFile2= new RandomAccessFile(file, "rwd");
randomAccessFile2.write(String.valueOf(currentThreadPostion).getBytes());
randomAccessFile2.close();
继承Thread类的DownloadThread类代码:
1 public static class DownloadThread extendsThread {2 private intthreadId;3 private intendThread;4 private intstartThred;5 public DownloadThread(int threadId, int startThred, intendThread) {6 this.threadId =threadId;7 this.startThred =startThred;8 this.endThread =endThread;9 }10 public voidrun() {11 //分段请求网络连接,分段保存在本地
12 synchronized (DownloadThread.class) {13 currentRunThreadCount += 1;14 }15 try{16 System.err.println("理论线程:"+threadId+",开始位置:"+startThred+",结束位置:"+endThread);17 URL url = newURL(path);18 HttpURLConnection connection =(HttpURLConnection) url.openConnection();19 connection.setRequestMethod("GET");20 connection.setConnectTimeout(10 * 1000);21 File file = new File(threadId+".txt");22 if(file.exists()) { //是否断点
23 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(newFileInputStream(file)));24 String lastPostion_str =bufferedReader.readLine();25 startThred =Integer.parseInt(lastPostion_str);26 bufferedReader.close();27 }28 //设置分段下载的头信息 Range:做分段
29 connection.setRequestProperty("Range", "bytes:"+startThred+"-" +endThread);30 int code =connection.getResponseCode();31 System.out.println(code);32 if(code == 200) { //200:请求全部资源成功 206:代表部分资源请求成功
33 InputStream inputStream =connection.getInputStream();34 System.out.println(getFileName(path));35 RandomAccessFile randomAccessFile = new RandomAccessFile(new File(getFileName(path)), "rw");36 randomAccessFile.seek(startThred);37 byte[] buffer = new byte[1024*10];38 int length = -1;39 int total = 0;//记录下载的总量
40 System.err.println("实际线程:"+threadId+",开始位置:"+startThred+",结束位置:"+endThread);41 while((length = inputStream.read(buffer)) != -1) {42 randomAccessFile.write(buffer, 0, length);43 total +=length;44 int currentThreadPostion = startThred +total;45 RandomAccessFile randomAccessFile2 = new RandomAccessFile(file, "rwd");46 randomAccessFile2.write(String.valueOf(currentThreadPostion).getBytes());47 randomAccessFile2.close();48 }49 randomAccessFile.close();50 inputStream.close();51 System.err.println("线程:"+threadId+"下载完毕");52 synchronized (DownloadThread.class) {53 currentRunThreadCount -= 1;54 if(currentRunThreadCount == 0){55 for(int i = 0; i < threadCount; i ++) {56 File file2 = new File(i+".txt");57 file2.delete();58 }59 }60 }61 }62
63 } catch(Exception e) {64 e.printStackTrace();65 }66
67
68 super.run();69 }70 }
View Code
完整代码:
1 importjava.io.BufferedReader;2 importjava.io.File;3 importjava.io.FileInputStream;4 importjava.io.InputStream;5 importjava.io.InputStreamReader;6 importjava.io.RandomAccessFile;7 importjava.net.HttpURLConnection;8 importjava.net.URL;9
10
11 public classexp6 {12
13 /**
14 *@paramargs15 */
16 private static int threadCount = 3;17 private static intblockSize;18 private static String path = "http://starry97.cn/a.txt";19 private static int currentRunThreadCount = 0;20 public static voidmain(String[] args) {21
22 try{23 URL url = newURL(path);24 HttpURLConnection connection =(HttpURLConnection) url.openConnection();25 connection.setRequestMethod("GET");26 connection.setConnectTimeout(10 * 1000);27 int code =connection.getResponseCode();28 if(code == 200) {29 int fileLength =connection.getContentLength();30 RandomAccessFile randomAccessFile = new RandomAccessFile(new File(getFileName(path)), "rw");31 randomAccessFile.setLength(fileLength);32 blockSize = fileLength /threadCount;33 for(int i = 0; i < threadCount; i ++) {34 int startThread = i *blockSize;35 int endThread = (i + 1) * blockSize - 1;36 if( i == blockSize - 1) endThread = fileLength -1;37 newDownloadThread(i, startThread, endThread).start();38
39 }40 }41 } catch(Exception e) {42 e.printStackTrace();43 }44
45 }46
47
48 public static class DownloadThread extendsThread {49 private intthreadId;50 private intendThread;51 private intstartThred;52 public DownloadThread(int threadId, int startThred, intendThread) {53 this.threadId =threadId;54 this.startThred =startThred;55 this.endThread =endThread;56 }57 public voidrun() {58 synchronized (DownloadThread.class) {59 currentRunThreadCount += 1;60 }61 //分段请求网络连接,分段保存在本地
62 try{63 System.err.println("理论线程:"+threadId+",开始位置:"+startThred+",结束位置:"+endThread);64 URL url = newURL(path);65 HttpURLConnection connection =(HttpURLConnection) url.openConnection();66 connection.setRequestMethod("GET");67 connection.setConnectTimeout(10 * 1000);68 File file = new File(threadId+".txt");69 if(file.exists()) { //是否断点
70 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(newFileInputStream(file)));71 String lastPostion_str =bufferedReader.readLine();72 startThred =Integer.parseInt(lastPostion_str);73 bufferedReader.close();74 }75 //设置分段下载的头信息 Range:做分段
76 connection.setRequestProperty("Range", "bytes:"+startThred+"-" +endThread);77 int code =connection.getResponseCode();78 System.out.println(code);79 if(code == 200) { //200:请求全部资源成功 206:代表部分资源请求成功
80 InputStream inputStream =connection.getInputStream();81 System.out.println(getFileName(path));82 RandomAccessFile randomAccessFile = new RandomAccessFile(new File(getFileName(path)), "rw");83 randomAccessFile.seek(startThred);84 byte[] buffer = new byte[1024*10];85 int length = -1;86 int total = 0;//记录下载的总量
87 System.err.println("实际线程:"+threadId+",开始位置:"+startThred+",结束位置:"+endThread);88 while((length = inputStream.read(buffer)) != -1) {89 randomAccessFile.write(buffer, 0, length);90 total +=length;91 int currentThreadPostion = startThred +total;92 RandomAccessFile randomAccessFile2 = new RandomAccessFile(file, "rwd");93 randomAccessFile2.write(String.valueOf(currentThreadPostion).getBytes());94 randomAccessFile2.close();95 }96 randomAccessFile.close();97 inputStream.close();98 System.err.println("线程:"+threadId+"下载完毕");99 synchronized (DownloadThread.class) {100 currentRunThreadCount -= 1;101 if(currentRunThreadCount == 0){102 for(int i = 0; i < threadCount; i ++) {103 File file2 = new File(i+".txt");104 file2.delete();105 }106 }107 }108 }109
110 } catch(Exception e) {111 e.printStackTrace();112 }113
114
115 super.run();116 }117 }118
119 public staticString getFileName(String path) {120 return path.substring(path.lastIndexOf("/")+1);121 }122
123 }
View Code