断点续传实现文件下载
2016-03-21 09:47
477 查看
package com.zzw.download; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class MultiThreadDownload { //规定下载服务器的资源用三条线程去下载 private static int threadCount =3; private static int currentRuningThread=3; // private static String path="http://192.168.102.18:8080/file.txt"; private static String path="http://192.168.102.18:8080/SIE.exe"; public static void main(String[] args) { //向服务器发送请求拿到要下载的文件的长度是多少 try { URL url=new URL(path); HttpURLConnection connection=(HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(5000); int code=connection.getResponseCode(); if (code==200) { //拿到文件的长度大小 int length=connection.getContentLength(); File file=new File(getFileName(path)); RandomAccessFile raf=new RandomAccessFile(file, "rw"); raf.setLength(length); raf.close(); //求出每一个线程下载的大小 int blockSize=length/threadCount; //启动线程去下载文件 for(int threadId=0;threadId<threadCount;threadId++){ int startIndex=threadId*blockSize; int endIndex=(threadId+1)*blockSize-1; if(threadId==(threadCount-1)){ endIndex=length-1; } //下载文件 new DownloadFilePartThread(threadId, startIndex, endIndex).start(); //续传文件 } } } catch (Exception e) { e.printStackTrace(); } } private static class DownloadFilePartThread extends Thread{ private int threadId;//线程的id号 private int startIndex;//线程下载的开始位置 private int endIndex;//线程下载的结束位置 private int currentPosition;//当前线程,下载到的位置 public DownloadFilePartThread(int threadId, int startIndex,int endIndex) { this.threadId=threadId; this.startIndex=startIndex; this.endIndex=endIndex; currentPosition=startIndex; } @Override public void run() { //去干下载 ----下载目标数据 //需要连接服务器 System.out.println("第"+threadId+"线程开始下载了:下载 从"+startIndex+"~"+endIndex); try { URL url=new URL(path); HttpURLConnection connection=(HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(5000); //在多线程下载的时候,每条线程只需要目标文件的一部分数据 //需要告诉服务器只需要那一段得数据 //通过设置http的请求头可以实现,告诉服务器,只需要目标端的数据 File file=new File(getFileName(path)); RandomAccessFile raf=new RandomAccessFile(file, "rw"); //startIndex-----endIndex connection.setRequestProperty("range", "bytes="+startIndex+"-"+endIndex); //获得服务器给返回的目标端的数据 File ilf=new File(threadId+".position"); if(ilf.exists()&&ilf.length()>0){ BufferedReader br =new BufferedReader(new FileReader(ilf)); String vl=br.readLine(); //得到当前写到的位置 int alreadyWritePosition=Integer.parseInt(vl); //从这个位置接着传输文件 connection.setRequestProperty("range", "bytes="+alreadyWritePosition+"-"+endIndex); raf.seek(alreadyWritePosition); System.out.println("文件"+threadId+"下载过"); } else{ connection.setRequestProperty("range", "bytes="+startIndex+"-"+endIndex); raf.seek(startIndex); } //返回的响应码是206(状态码)-----代表部分数据 int code=connection.getResponseCode(); if(code==206){ //拿到数据 InputStream in=connection.getInputStream(); //将得到的数据写入到文件中 //要告诉从哪个位置开始写 int len=0; byte[] buf=new byte[1024*1024]; while((len=in.read(buf))>0){ raf.write(buf,0,len); //将实时的位置给记录了下来,记录之后,紧接着要往 文件中继续写 currentPosition=currentPosition+len; File info=new File(threadId+".position"); //因为要频繁的使用底层文件所以要用Random中的 “rwd”----d写入底层设备 RandomAccessFile rf=new RandomAccessFile(info, "rwd"); // OutputStream out=new FileOutputStream(info); // out.write((currentPosition+"").getBytes()); rf.write(String.valueOf(currentPosition).getBytes()); rf.close(); } in.close(); raf.close(); } System.out.println("第"+threadId+"线程下载结束了"); //等待所有的线程都下载完成后再去删除文件 //弄一个计数器,记住总共多少条线程正在下载,每当下载玩一个线程currentRuningthread就减一 //当currentRuningthread小于或者等于0的时候代表所有文件下载结束这时将记录下载位置的文件删除 //因为涉及到线程切换的问题所以我们要进行synchronized(类){} synchronized (MultiThreadDownload.class) { currentRuningThread--; if(currentRuningThread<=0){ //将记录下载位置的文件删除 File ill=new File(threadId+".position"); //重命名记录文件 ill.renameTo(new File(threadId+".position.finish")); for(threadId=0;threadId<threadCount;threadId++){ File illd=new File(threadId+".position.finish"); illd.delete(); } } } } catch (Exception e) { e.printStackTrace(); } } } public static String getFileName(String path){ int index=path.lastIndexOf("/"); return path.substring(index+1); } }
相关文章推荐
- 2016.03.18-2016.03.20回顾
- mybatis动态条件查询和翻页查询的例子
- XE开发IOS下中文,英文,数字不对齐的解决办法
- iOS开发Xcode7真机调试教程
- CSS去掉 a 标签点击后出现的虚线框
- 前端调用后端的方法(基于restful接口的mvc架构)
- 微信语音idk的demo学习
- 【IndiaHacks 2016 - Online Edition (Div 1 + Div 2) ErrichtoC】【脑洞 好题 讨论?NO!暴力】Bear and Up-Down 多少种一次交
- (二十二)享元模式
- PHP PSR-3 基本代码规范(中文版)
- Android WebView使用总结
- vs2008快捷键大全
- hyperic agent结构
- RxJava入门指南
- 数据类型
- CKEditor4.x整合教程-Xproer.WordPaster
- Sql动态添加字段的正确姿势
- SAP内部转移定价
- String.format()用法
- SAP事业部内部互供