多线程分段下载文件
http://aokunsang.iteye.com/blog/1069794
断点续传的原理:
把一个文件分为n个小文件,程序分n个线程去下载每一个小文件。阅读有关资料,IE浏览器传递给服务端的时候可以传递一个请求信息"Range":如:RANGE: bytes=2000070- 一看就知道告诉服务器下载的时候从2000070字节开始下载。值得注意的是response.getResponseCode()为206,不再是200了。
上代码:
1 /** 2 * 下载工具类 3 * 4 * @author aokunsang 5 * 6 */ 7 public class FileDownloader { 8 9 private HttpURLConnection conn; 10 11 public static void main(String[] args) throws Exception { 12 FileDownloader load = new FileDownloader(); 13 load.download(); 14 } 15 16 /** 17 * 开始下载 18 */ 19 public void download() throws Exception { 20 HttpConnect connect = new HttpConnect(1); 21 int fileSize = 0, threadSize = 3; // 文件长度和线程数 22 conn = connect.initConnction(); 23 conn.connect(); 24 if (conn.getResponseCode() == 200) { 25 fileSize = conn.getContentLength(); 26 conn.disconnect(); 27 } 28 int perthThreadSize = fileSize / 3 + 1; //每个线程需要下载的文件大小 29 RandomAccessFile raf = new RandomAccessFile(new File("D://ca.mp3"), "rw"); 30 raf.setLength(fileSize); 31 raf.close(); 32 long startTime = System.currentTimeMillis(); 33 for (int i = 0; i < threadSize; i++) { 34 int startpos = i * perthThreadSize; //线程开始下载的位置 35 RandomAccessFile raff = new RandomAccessFile(new File("D://ca.mp3"), "rw"); 36 raff.seek(startpos); 37 new myThread(startpos, perthThreadSize, i, raff).start(); 38 } 39 long endTime = System.currentTimeMillis(); 40 41 while(Thread.activeCount()>1){} //防止main线程结束而导致下载线程被销毁 42 System.out.println("--------------下载完成,共耗时:"+(endTime-startTime)/(60*1000)+"分钟--------"); 43 } 44 45 class myThread extends Thread { 46 private int startpos; 47 private int perThreadSize; 48 private int threadId; 49 private RandomAccessFile raf; 50 51 public myThread(int startpos, int perThreadSize, int threadId, 52 RandomAccessFile raf) { 53 this.startpos = startpos; 54 this.perThreadSize = perThreadSize; 55 this.threadId = threadId; 56 this.raf = raf; 57 } 58 59 @Override 60 public void run() { 61 HttpConnect connect = new HttpConnect(0); 62 HttpURLConnection con = connect.initConnction(); 63 con.setRequestProperty("Range", "bytes=" + this.startpos + "-"); 64 try { 65 InputStream is = con.getInputStream(); 66 byte[] bt = new byte[1024]; 67 int length = 0; 68 int len = 0; 69 while (length < this.perThreadSize && (len = is.read(bt)) != -1) { 70 raf.write(bt, 0, len); 71 length += len; 72 } 73 raf.close(); 74 is.close(); 75 System.out.println("线程"+threadId+"完成!"); 76 } catch (Exception e) { 77 e.printStackTrace(); 78 } 79 } 80 } 81 82 class HttpConnect { 83 private int flag; 84 85 public HttpConnect(int flag) { 86 this.flag = flag; 87 } 88 89 public HttpURLConnection initConnction() { 90 HttpURLConnection connection = null; 91 try { 92 URL url = new URL(HttpConnectParams.URLSTRING.content); 93 connection = (HttpURLConnection) url.openConnection(); 94 connection.setConnectTimeout(Integer 95 .parseInt(HttpConnectParams.CONNECTTIEMEDOUT.content)); 96 connection.setRequestMethod(HttpConnectParams.POST.content); 97 connection.setRequestProperty(HttpConnectParams.ACCECT.header, 98 HttpConnectParams.ACCECT.content); 99 connection.setRequestProperty( 100 HttpConnectParams.ACCECT_LANGAGE.header, 101 HttpConnectParams.ACCECT_LANGAGE.content); 102 connection.setRequestProperty(HttpConnectParams.CHARSET.header, 103 HttpConnectParams.CHARSET.content); 104 if (flag == 1) { 105 connection.setRequestProperty( 106 HttpConnectParams.KEEPCONNECT.header, 107 HttpConnectParams.KEEPCONNECT.content); 108 } 109 } catch (Exception e) { 110 connection = null; 111 } 112 return connection; 113 } 114 } 115 }
---/---
1 * HTTP请求的一些常量信息 2 * @author aokunsang 3 * 4 */ 5 public enum HttpConnectParams { 6 /** 7 * URL地址(mp3格式的音乐文件) 8 */ 9 URLSTRING("http://www.61mp3.cn/music/%B6%F9%CD%AF%B8%E8%C7%FA/%CA%AE%B6%FE%C9%FA%D0%A4%B8%E8.mp3"), 10 /** 11 * 请求的方式 12 */ 13 POST("GET"), 14 /** 15 * 请求的格式 16 */ 17 ACCECT("Accept","image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"), 18 /** 19 * 请求的语言 20 */ 21 ACCECT_LANGAGE("Accept-Language","zh-CN"), 22 /** 23 * 请求的字符集编码 24 */ 25 CHARSET("Charset","UTF-8"), 26 /** 27 * 链接的超时数 28 */ 29 CONNECTTIEMEDOUT("5000"), 30 /** 31 * 保持链接 32 */ 33 KEEPCONNECT("Connection","Keep-Alive"); 34 35 public String header; //标题 36 public String content; //内容 37 38 private HttpConnectParams(String header,String content) { 39 this.header = header; 40 this.content = content; 41 } 42 private HttpConnectParams(String content){ 43 this.content = content; 44 } 45 }