代码实现了多线程下载和断点续传功能
1 import java.io.BufferedReader; 2 import java.io.File; 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.io.InputStreamReader; 8 import java.io.RandomAccessFile; 9 import java.net.HttpURLConnection; 10 import java.net.URL; 11 12 import javax.print.attribute.standard.Finishings; 13 14 public class MultiDownload { 15 16 static int ThreadCount = 3; 17 static int finishedThread = 0; 18 //确定下载地址 19 static String path = "http://192.168.13.13:8080/QQPlayer.exe"; 20 public static void main(String[] args) { 21 22 //发送get请求,请求这个地址的资源 23 try { 24 URL url = new URL(path); 25 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 26 conn.setRequestMethod("GET"); 27 conn.setConnectTimeout(5000); 28 conn.setReadTimeout(5000); 29 30 if(conn.getResponseCode() == 200){ 31 //拿到所请求资源文件的长度 32 int length = conn.getContentLength(); 33 34 File file = new File("QQPlayer.exe"); 35 //生成临时文件 36 RandomAccessFile raf = new RandomAccessFile(file, "rwd"); 37 //设置临时文件的大小 38 raf.setLength(length); 39 raf.close(); 40 //计算出每个线程应该下载多少字节 41 int size = length / ThreadCount; 42 43 for (int i = 0; i < ThreadCount; i++) { 44 //计算线程下载的开始位置和结束位置 45 int startIndex = i * size; 46 int endIndex = (i + 1) * size - 1; 47 //如果是最后一个线程,那么结束位置写死 48 if(i == ThreadCount - 1){ 49 endIndex = length - 1; 50 } 51 // System.out.println("线程" + i + "的下载区间是:" + startIndex + "---" + endIndex); 52 new DownLoadThread(startIndex, endIndex, i).start(); 53 } 54 } 55 } catch (Exception e) { 56 // TODO Auto-generated catch block 57 e.printStackTrace(); 58 } 59 } 60 61 62 } 63 class DownLoadThread extends Thread{ 64 int startIndex; 65 int endIndex; 66 int threadId; 67 68 public DownLoadThread(int startIndex, int endIndex, int threadId) { 69 super(); 70 this.startIndex = startIndex; 71 this.endIndex = endIndex; 72 this.threadId = threadId; 73 } 74 75 @Override 76 public void run() { 77 //再次发送http请求,下载原文件 78 try { 79 File progressFile = new File(threadId + ".txt"); 80 //判断进度临时文件是否存在 81 if(progressFile.exists()){ 82 FileInputStream fis = new FileInputStream(progressFile); 83 BufferedReader br = new BufferedReader(new InputStreamReader(fis)); 84 //从进度临时文件中读取出上一次下载的总进度,然后与原本的开始位置相加,得到新的开始位置 85 startIndex += Integer.parseInt(br.readLine()); 86 fis.close(); 87 } 88 System.out.println("线程" + threadId + "的下载区间是:" + startIndex + "---" + endIndex); 89 HttpURLConnection conn; 90 URL url = new URL(MultiDownload.path); 91 conn = (HttpURLConnection) url.openConnection(); 92 conn.setRequestMethod("GET"); 93 conn.setConnectTimeout(5000); 94 conn.setReadTimeout(5000); 95 //设置本次http请求所请求的数据的区间 96 conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); 97 98 //请求部分数据,相应码是206 99 if(conn.getResponseCode() == 206){ 100 //流里此时只有1/3原文件的数据 101 InputStream is = conn.getInputStream(); 102 byte[] b = new byte[1024]; 103 int len = 0; 104 int total = 0; 105 //拿到临时文件的输出流 106 File file = new File("QQPlayer.exe"); 107 RandomAccessFile raf = new RandomAccessFile(file, "rwd"); 108 //把文件的写入位置移动至startIndex 109 raf.seek(startIndex); 110 while((len = is.read(b)) != -1){ 111 //每次读取流里数据之后,同步把数据写入临时文件 112 raf.write(b, 0, len); 113 total += len; 114 // System.out.println("线程" + threadId + "下载了" + total); 115 116 //生成一个专门用来记录下载进度的临时文件 117 RandomAccessFile progressRaf = new RandomAccessFile(progressFile, "rwd"); 118 //每次读取流里数据之后,同步把当前线程下载的总进度写入进度临时文件中 119 progressRaf.write((total + "").getBytes()); 120 progressRaf.close(); 121 } 122 System.out.println("线程" + threadId + "下载完毕-------------------小志参上!"); 123 raf.close(); 124 125 MultiDownload.finishedThread++; 126 synchronized (MultiDownload.path) { 127 if(MultiDownload.finishedThread == MultiDownload.ThreadCount){ 128 for (int i = 0; i < MultiDownload.ThreadCount; i++) { 129 File f = new File(i + ".txt"); 130 f.delete(); 131 } 132 MultiDownload.finishedThread = 0; 133 } 134 } 135 136 } 137 } catch (Exception e) { 138 // TODO Auto-generated catch block 139 e.printStackTrace(); 140 } 141 } 142 }