多线程下载,断点续传

public class MutiThradDownload {
	//使用3条线程去下载
	private static int threadCount = 3;//你要不要多少个下载的线程同时下载
	private static  String path = "http://192.168.10.157:8080/QQ.apk";//地址
   public static void main(String[] args) {
	//向服务器发请求,要下载的长度是多少
	   try {
		URL  url = new URL(path);
		HttpURLConnection  conn = (HttpURLConnection) url.openConnection();
		conn.setConnectTimeout(5000);
		conn.setRequestMethod("GET");
		int code = conn.getResponseCode();
		if (code==200) {
			int lenth = conn.getContentLength();
			File file = new File(getFilename(path));//截取后缀部分最后文件名
			RandomAccessFile  raf = new RandomAccessFile(file,"rw");//文件类型为读写模式
			raf.setLength(lenth);//设置文件的大小和目标文件大小一致
			raf.close();
			
			
			//每块线程下载的大小
			int blockSize = lenth/threadCount;//确定每个线程下载的大小
			System.out.println("文件总大小为"+lenth);
			for (int threadId = 0; threadId < threadCount; threadId++) {
				int startIndex = threadId*blockSize;
				int endIndex = (threadId+1)*blockSize-1;
				if (threadId==threadCount-1) {//用if来判断是否是最后一个线程,如果是则最后一个线程的结束就是文件的大小
					endIndex = lenth-1;
				}
			new DownloadPart(threadId, startIndex, endIndex).start();//开启线程准备下载
//				 System.out.println("第"+threadId+"线程:从"+startIndex+"~"+endIndex);
			}
			
		}
		
		
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	   
}
   
   private static class DownloadPart extends Thread{
	   private int threadId; //线程ID
	private int startIndex; //线程开始的索引
	private int endIndex;   //线程结束的索引
	private int currentPosition;//当前位置下载的位置
	public DownloadPart (int threadId,int startIndex,int endIndex){
		   this.threadId = threadId;
		   this.startIndex = startIndex;
		   this.endIndex = endIndex;
		   this.currentPosition = startIndex;//第一次进来的时候线程当前的下载位置就是开始位置
	   }
	   @Override
	public void run() {
			 System.out.println("第"+threadId+"线程:开始下载了"+startIndex+"~"+endIndex);
		   //在这里干下载的事情,下载目标的部分的数据
		   try {
			URL  url= new URL(path);
			HttpURLConnection   conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			conn.setRequestMethod("GET");
			
			File file = new File(getFilename(path));
			RandomAccessFile  raf = new RandomAccessFile(file, "rw");//随机读写的一个类在多线程下载里面很是重要
			
			conn.setRequestProperty("range", "bytes="+startIndex+"-"+endIndex);//这个Connection里面的一个很重要的方法通过这个方法我们可以向服务器发送请求,所需要的数据
			
			System.out.println("----"+threadId);
			File ilf = new File(threadId+".position");
			if (ilf.exists()&&ilf.length()>0) {//如果问价存在的话说明之前就已经下载过了  此时的开始索引就会有所改变
				System.out.println("之前下载过");
				BufferedReader  br = new BufferedReader(new FileReader(ilf));
				String vl  = br.readLine();
				int alreadlywriteposition = Integer.parseInt(vl);
				//从这个位置开始要
				conn.setRequestProperty("range", "bytes="+alreadlywriteposition+"-"+endIndex);
			    raf.seek(alreadlywriteposition);//
			}else{
				System.out.println("之前没有下载过");
				conn.setRequestProperty("range", "bytes="+startIndex+"-"+endIndex);
			    raf.seek(startIndex);
			}
			
			
			
			//获得返回的目标端的数据
			int code = conn.getResponseCode();
			if (code==206) {
				InputStream  in = conn.getInputStream();
				
				int len = 0 ;
				byte[]  buf = new byte[1024];
				while ((len=in.read(buf))>0) {
               			raf.write(buf,0,len);
               			//将实时的位置及记录了下来
               			currentPosition = currentPosition+len;//没下载一点都会保存下来,下次继续下载的时候会根据这个值来判断从哪里开始下载
               			File info = new File(threadId+".position");//保存到一个文件里面
               			OutputStream  out = new FileOutputStream(info);
               			out.write(String.valueOf(currentPosition).getBytes());
               			out.close();
               			
				}
				 
				
				
				
				
				
				raf.close();
				in.close();
			}
			 System.out.println("第"+threadId+"线程下载结束了");

 //下载结束后将记录的文件删掉
            synchronized (MutiThradDownload.class) {
                currentcount--;
                 if (currentcount<=0){
                    //所有的线程都下载完了,将就下载的文件都删掉
                     File fff = new File(threadId+".position");
                     fff.renameTo(new File(threadId+".position"));
                     for (int threadid = 0; threadid <threadCount; threadid++) {
                        File fll = new File(threadId+".position");
                        fll.delete();
                    }
                }
            }


                         } catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		   
		   
		   
	}
   }
   public static String getFilename(String path){
       int index = path.lastIndexOf("/");
       return path.substring(index+1);
       /**
        * 解释下substring这个方法,他表示的是从当前位置到字符串末尾截取的字符串
        * 这里是以/为届,最后一个索引截取,在index加一表示从下一个位置开始获得
        */
   }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值