package cn.itcast.download;
import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
/***
* 多线程下载类:
* 一般的所有断点下载工具都会在下载开始生成两个文件:
* 一个是与网络资源大小相同的空文件,一个是配置文件,
* 该配置文件分别记录每个线程已经下载到了哪个字节,当网络断开后再次下载时,
* 每个线程根据配置文件里记录的位置向后下载即可。
* 未实现:进度条、断点下载、线程池管理
* @author huawei
*
*/
public class MulThreadDownload {
//入口
public static void main(String[] args) throws Exception {
String path = "http://192.168.1.102:8080/web/AndroidAPI.chm";
new MulThreadDownload().download(path, 3);
}
private void download(String path, int threadsize) throws Exception {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if(conn.getResponseCode() == 200){
//取得待下载文件的长度:用于给每个线程分配下载量
int length = conn.getContentLength();
File file = new File(getFileName(path));
//主要操作文件类型为:"rwd",即及时写入
RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
//将文件设置和待下载文件一样的长度大小的空间
accessFile.setLength(length);
accessFile.close();
//计算每条线程负责下载数据量
int block = length % threadsize == 0 ?length/threadsize : length/threadsize + 1;
//创建线程
for(int threadid = 0;threadid < threadsize; threadid++){
new DownloadThread(threadid, block, url, file).start();
}
}else{
System.out.println("下载链接失败");
}
}
//线程:
private class DownloadThread extends Thread{
private int threadid;
private int block;
private URL url;
private File file;
public DownloadThread(int threadid, int block, URL url, File file) {
this.threadid = threadid;
this.block = block;
this.url = url;
this.file = file;
}
public void run() {
//取得当前线程开始下载的位置
int start = threadid * block;
//取得当前线程结束下载的位置
int end = (threadid + 1) * block - 1;
System.out.println(start+"--"+end);
try {
RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
//将游标移动到每个线程的开始处
accessFile.seek(start);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
//设置向web请求下载的区间:http下载支持Range属性
conn.setRequestProperty("Range", "bytes=" + start +"-" + end);
//注意:分区间下载的返回码为206
if(conn.getResponseCode() == 206){
InputStream in = conn.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len = in.read(buffer)) != -1){
accessFile.write(buffer, 0, len);
}
in.close();
}
accessFile.close();
System.out.println("线程"+ (threadid + 1) +"下载完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}
//获取保存文件名
private String getFileName(String path) {
return path.substring(path.lastIndexOf("/") + 1);
}
}