您的位置:首页 > 其它

断点续传实现文件下载

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);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: