Java实现多线程下载及断点续传

时间:2022-02-06 21:13:16
packagecom.sli.thread;
importjava.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.RandomAccessFile; 
import java.net.HttpURLConnection; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.util.Date;
public class Main extendsThread {
 Stringurlt=""; 
 int startl; 
 int end; 
 String fileName; 
 RandomAccessFile osf; 
 public Main(int i, String url, String fileName,int start, int end) { 
  this.setName("thread" + i); //子线程名称 
  this.urlt = url; //下载地址 
  this.fileName =fileName; 
  this.startl = start; //子线程读取/写入起始字节 
  this.end = end;//子线程写入结束字节长度 
 }

 public void run() { 
  try{ 
   osf = newRandomAccessFile(fileName, "rw"); 
   URL url = newURL(urlt); 
   HttpURLConnectionhttp2 = (HttpURLConnection)url.openConnection(); 
   http2.setRequestProperty("User-Agent","NetFox"); 
    
   http2.setRequestProperty("RANGE","bytes=" + startl + "-");//设置断点位置,向服务器请求从文件的哪个字节开始读取。 
   osf.seek(startl);//设置本地文件从哪个字节开始写入 
   InputStreaminput = http2.getInputStream(); 
   byte b[] =new byte[1024];// 设置缓冲池,每次只读1024字节 
   Date d = newDate();// 子线程开始下载时间 
   int l;//计算子线程读取和写入的文件长度,当长度大于每个子线程平均下载长度则终止线程 
   inti; 
   l =0; 
   System.out.println(this.getName()+ " 开始下载。。。"); 
   while ((i =input.read(b, 0, 1024)) != -1 && l < end) { //线程下载字节长度控制误差小于缓冲池大小,本示例为缓冲池1024字节 
    osf.write(b,0, i); 
    b= new byte[1024];// 重新赋值,避免重新读入旧内容 
    l+= i; 
   } 
   Date d2 = newDate();// 子线程结束下载时间 
   System.out.println(this.getName()+ " 线程耗时: " 
     +(d2.getTime() - d.getTime()) / 1000 + " 秒,实际共下载:" +l 
     +"字节");// 子线程下载耗时(秒) 
  } catch (FileNotFoundExceptione1) { 
   // TODOAuto-generated catch block 
   e1.printStackTrace(); 
  } catch (MalformedURLExceptione) { 
   // TODOAuto-generated catch block 
   e.printStackTrace(); 
  } catch (IOException e){ 
   // TODOAuto-generated catch block 
   e.printStackTrace(); 
  }
 }
}
 
 
packagecom.sli.thread;
importjava.io.File; 
import java.io.IOException; 
import java.io.RandomAccessFile; 
import java.net.HttpURLConnection; 
import java.net.URL;
public class DownLoad{ 
  
 static int len;//线程平均下载文件长度 
 static int bn;//每个线程写入文件的字节数 
 static int tn; // 线程数 
 static String urlt;//下载地址 
 static StringfileName; 
 static RandomAccessFile osf; // 文件操作
 publicstatic void main(String[] args) {
  try{ 
   urlt ="  http://c758482.r82.cf2.rackcdn.com/SublimeText 2.0.zip"; 
   fileName ="C:\\" 
     +urlt.split("//")[1].split("/")[urlt.split("//")[1] 
       .split("/").length- 1]; 
   System.out.println(fileName); 
   URL url = newURL(urlt); 
   HttpURLConnectionhttp = (HttpURLConnection)url.openConnection(); 
    
   System.out.println("filesize:" + http.getContentLength()); 
   tn=10; 
   len =http.getContentLength() / tn;//舍去余数(余数自动舍去)计算每个线程应下载平均长度,最后一个线程再加上余数,则是整个文件的长度, 
   File f = newFile(fileName); 
   if(f.exists()) { 
    f.delete(); 
    osf= new RandomAccessFile(f, "rw"); 
    osf.seek(http.getContentLength()- 1); 
    osf.write(0); 
   } else{ 
    osf= new RandomAccessFile(f, "rw"); 
    osf.seek(http.getContentLength()- 1); 
    osf.write(0); 
   } 
   System.out.println("temp文件长度:" + f.length()); 
   Thread t;//下载子线程, 
   for (int j =0; j < tn; j++) { 
    if(j == tn - 1) {// 如果最后一个线程则加上余数长度字节 
     bn= len + (http.getContentLength() % tn); 
    }else { 
     bn= len; 
    } 
    System.out 
      .println("t"+ j + "线程下载长度:" + bn + "起始字节:" + len *j); 
    t= new Main(j, urlt, fileName, len * j, bn
    ); 
    t.start(); 
   }
  } catch (IOException e){ 
   e.printStackTrace(); 
  } 
 }