多线程下载大文件(断点续传)
RandomAccessFile
提到多线程下载大文件或者时断点续传,我们就肯定要提到 RandomAccessFile这个类,为啥可以多线程来下载一个大文件呢?得益于它强大的seek方法
然后提到断点续传呢,我觉得可以聊一聊Connection 头字段相关的内容
Connection
这个字段只在http 1.1 协议中存在。它决定了客户端和服务器进行了一次会话后,服务器是否立即关闭网络连接。
Connect有两个值:
-
close 当read完数据时,就立即返回 keep-alive read完数据后,还得被阻塞一段时间,直到超时时间
http请求头字段
-
Host 用于指定访问的主机名和端口号 Accept 确定客户端可以接受的媒体类型 User-Agent 指定客户端用什么方式访问的服务器 Range 利用该字段头来实现断点续传功能 (Range: bytes=1000-2000 传输范围时 1000-2000 Range: bytes=1000- 传输1000字节之后的数据)
http响应头字段
-
Accept-Ranges 服务器是否支持断点续传 Content-Range 指定返回的web资源的字节范围
利用RandomAccessFile 实现多线程下载文件
public class RandomAccessFileTest {
private final static int DEFAULT_THREAD_SIZE = 5;
/**
* 下载文件的方法(内部通过RandomAccessFile实现多线程下载文件)
* @param url 下载链接
* @param destLocation 目标下载地址
*/
public void download(String url, String destLocation) {
File dest = new File(destLocation);
int fileSize = computeFileSize(url);
if(fileSize <=0) {
throw new RuntimeException("读取文件失败");
}
int singleSize = fileSize / DEFAULT_THREAD_SIZE;
for(int i=0; i<DEFAULT_THREAD_SIZE; i++) {
int startIndex = i * singleSize;
int endIndex = (i+1) * singleSize;
if(i == DEFAULT_THREAD_SIZE-1) {
endIndex = fileSize;
}
new DownloadThread(url, dest, startIndex, endIndex).start();
}
}
/**
* 计算需要下载的文件大小
* @param url 下载链接
* @return 文件大小
*/
private int computeFileSize(String url) {
try {
URL address = new URL(url);
HttpURLConnection connection = (HttpURLConnection) address.openConnection();
if(connection.getResponseCode() == 200) {
return connection.getContentLength();
}
connection.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
return 0;
}
class DownloadThread extends Thread{
private String url;
private File destFile;
private int startIndex;
private int endIndex;
public DownloadThread(String url, File destFile, int startIndex, int endIndex) {
super();
this.url = url;
this.destFile = destFile;
this.startIndex = startIndex;
this.endIndex = endIndex;
}
@Override
public void run() {
try {
URL address = new URL(url);
HttpURLConnection connection = (HttpURLConnection) address.openConnection();
//设置请求参数
connection.setRequestProperty("User-Agent", "NetFox");
connection.setRequestProperty("RANGE", "bytes="+startIndex+"-"+endIndex);
connection.connect();
//写文件
RandomAccessFile raFile = new RandomAccessFile(destFile, "rw");
raFile.seek(startIndex);
InputStream inputStream = connection.getInputStream();
BufferedInputStream bis = new BufferedInputStream(inputStream);
int len = 0;
byte[] b = new byte[2048];
while ((len = bis.read(b)) != -1) {
raFile.write(b,0,len);
}
bis.close();
raFile.close();
connection.disconnect();
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
上一篇:
IDEA上Java项目控制台中文乱码
