import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
public class Demo {
//线程个数
public static int threadCount = 3
;
//线程下载完成的个数
public static int finishedCount = 3
;
/**
* 多线程下载测试类
* @param args
* @throws Exception
*/
public static void main(String[] args)
throws Exception {
//1、连接服务器,获取一个文件,获取文件的长度,在本地创建一个大小跟服务器文件一样大的临时文件
String path = "http://192.168.1.100:8080/test.avi"
;
URL url =
new URL(path);
HttpURLConnection conn =
(HttpURLConnection)url.openConnection();
conn.setConnectTimeout(5000
);
conn.setRequestMethod("GET"
);
int code =
conn.getResponseCode();
if(code==200
)
{
//服务器返回的数据长度 实际上就是文件的长度
int length =
conn.getContentLength();
System.out.println("文件总长度:"+
length);
//在客服端创建出来一个大小跟服务器端文件一样大小的临时文件
RandomAccessFile raf =
new RandomAccessFile("test.avi", "rwd"
);
//指定创建的这个文件的长度
raf.setLength(length);
raf.close();
//假设是3个线程去下载资源
//平均每一个线程下载的文件的大小
int blockSize = length /
threadCount;
for(
int threadId=1;threadId<=threadCount;threadId++
)
{
//线程下载的开始位置
int startIndex = (threadId-1)*
blockSize;
int endIndex = threadId*
blockSize;
if(threadId==
threadCount)
{
endIndex =
length;
}
System.out.println("线程:"+threadId+" 下载:---"+startIndex+"--->"+
endIndex);
//启动线程
new DownloadThread(threadId,startIndex,endIndex,path).start();
}
}
else
{
System.out.println("服务器错误"
);
}
}
public static class DownloadThread
extends Thread
{
private int threadId;
//线程id
private int startIndex;
private int endIndex;
private String path;
public DownloadThread(
int threadId,
int startIndex,
int endIndex,
String path) {
super();
this.threadId =
threadId;
this.startIndex =
startIndex;
this.endIndex =
endIndex;
this.path =
path;
}
public void run() {
try {
//检查是否存在记录文件下载长度的文件,如果存在读取这个文件的数据
File tempFile =
new File(threadId+".txt"
);
if(tempFile.exists() && tempFile.length() >0
)
{
FileInputStream fis =
new FileInputStream(tempFile);
byte[] temp =
new byte[1024
];
int leng =
fis.read(temp);
String downloadLen =
new String(temp,0
,leng);
int downloadLenInt =
Integer.parseInt(downloadLen);
startIndex =
downloadLenInt;
fis.close();
}
System.out.println("线程:"+threadId+"实际下载:---"+startIndex+"--->"+
endIndex);
URL url =
new URL(path);
HttpURLConnection conn =
(HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000
);
conn.setRequestMethod("GET"
);
//重要 : 请求服务器下载部分的文件指定文件的位置
conn.setRequestProperty("Range", "bytes="+startIndex+"-"+
endIndex);
//从服务器请求全部资源 200 ok 如果从服务器请求部分资源 206 ok
int code =
conn.getResponseCode();
System.out.println("code:"+
code);
//已经设置了请求的位置 返回的事当前位置对应的文件的输入流
InputStream is =
conn.getInputStream();
//在客服端创建出来一个大小跟服务器端文件一样大小的临时文件
RandomAccessFile raf =
new RandomAccessFile("test.avi", "rwd"
);
//随机写文件的时候从哪个位置开始
raf.seek(startIndex);
//定位文件
int len = 0
;
byte[] buffer =
new byte[1024
];
int total = 0
;
while((len=is.read(buffer))!=-1
)
{
//记录已经下载完成的长度
RandomAccessFile recordFile =
new RandomAccessFile(threadId+".txt","rwd"
);
raf.write(buffer,0
,len);
//下载完成的长度
total +=
len;
recordFile.write((total+startIndex +""
).getBytes());
recordFile.close();
}
is.close();
raf.close();
System.out.println("线程:"+threadId+"下载完毕了。。。"
);
} catch (Exception e) {
e.printStackTrace();
}finally
{
//用于删除各个线程记录已经下载完成的长度的文件
finishedCount--
;
//所有线程下载完成
if(finishedCount==0
)
{
for(
int i=1;i<=threadCount;i++
)
{
//删除记录文件
File deleteFile =
new File(i+".txt"
);
deleteFile.delete();
}
}
}
}
}
}
转载于:https://www.cnblogs.com/zoro-zero/p/3955015.html
相关资源:Java实现多线程断点下载实例代码(下载过程中可以暂停)