package cn.itcast.download;
import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
/*多线程文件下载实例*/
public class MulThreadDownloader {
public static void main(String[] args) throws Exception {
String path = "http://192.168.1.100:8080/web/QQWubiSetup.exe";
int threadsize = 3;
new MulThreadDownloader().download(path, threadsize);
}
/**
* 下载文件
* @param 网络路径,文件大小
*/
private void download(String path, int threadsize) throws Exception {
URL downpath = new URL(path);
HttpURLConnection conn = (HttpURLConnection) downpath.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if(conn.getResponseCode() == 200){
//@获取网络文件长度
int length = conn.getContentLength();
//@在本地创建一个与服务器相同的文件
File file = new File(getFileName(path)); //只要不给定目录,文件将被创建于项目根目录下
RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");//r;只读;rw:读写;rws:将文件的元数据和内容数据立刻同步
//到设备中;rwd:只将内容数据同步到设备中。(一般情况下
//是写到缓存当中,为防止手机突然断点,故必须使用同步数据)
//注:元数据指文件的创建时间,作者等;内容数据值文件的
//内容。
//@设置文件对象长度
accessFile.setLength(length);
accessFile.close();
//@计算每条线程负责下载的数据量
int block = length % threadsize == 0 ? length / threadsize : length / threadsize +1;
for(int threadid = 0 ; threadid < threadsize ; threadid++){
/**
* @开启文件下载线程
* @param 线程ID,文件下载路径,每个线程负责下载数据量,本地文件对象
*/
new DownloadThread(threadid, downpath, block, file).start();
}
}
}
//下载线程的定义
private final class DownloadThread extends Thread{
private int threadid;
private URL downpath;
private int block;
private File file;
public DownloadThread(int threadid, URL downpath, int block, File file) {
this.threadid = threadid;
this.downpath = downpath;
this.block = block;
this.file = file;
}
public void run() {
//计算该线程从网络文件起始下载位置
int startposition = threadid * block;
//计算下载到网络文件的终止位置
int endposition = (threadid+1) * block - 1;
try{
RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
accessFile.seek(startposition);//设定网络文件数据存放区域
HttpURLConnection conn = (HttpURLConnection) downpath.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
//该字段设定从网络文件的某个区域下载数据
conn.setRequestProperty("Range", "bytes="+ startposition+ "-"+ endposition);
//分段请求数据的返回值为206
if(conn.getResponseCode() == 206){
InputStream inStream = conn.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while( (len = inStream.read(buffer)) != -1 ){
accessFile.write(buffer, 0, len);
}
accessFile.close();
inStream.close();
System.out.println("第"+ (threadid+1)+ "条线程下载完成");
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 从路径中截取网络文件名称
*/
private static String getFileName(String path) {
return path.substring(path.lastIndexOf("/")+ 1);
}
}