package rui.study.coding2017.jobs3.download;
import rui.study.coding2017.jobs3.download.api.Connection;
import rui.study.coding2017.jobs3.download.api.ConnectionException;
import rui.study.coding2017.jobs3.download.api.ConnectionManager;
import rui.study.coding2017.jobs3.download.api.DownloadListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
public class FileDownloader {
public static int threadNum=5;
String url;
DownloadListener listener;
ConnectionManager cm;
private static String filePath;
static String path="D:\\360downloads";
File pathFile;
public static String getFilePath() {
return filePath;
}
public FileDownloader(String _url) {
this.url = _url;
filePath=path+"/"+url.substring(url.lastIndexOf("/")+1);
pathFile=new File(path);
if(!pathFile.exists()||!pathFile.isDirectory()){
pathFile.mkdir();
}
}
public void setListener(DownloadListener listener) {
this.listener = listener;
}
public void setConnectionManager(ConnectionManager ucm){
this.cm = ucm;
}
public void execute(){
Connection conn = null;
try {
conn = cm.open(this.url);
int length = conn.getContentLength();
setRandomAccessFile(length);
List<DownloadThread> list = getDownloadThreads(conn, length);
waitForDownLoad(list);
listener.notifyFinished();
} catch (ConnectionException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
if(conn != null){
conn.close();
}
}
}
/**
* 配置 随机访问文件
* 预分配文件所占的磁盘空间,磁盘中会创建一个指定大小的文件;
* @param length
* @throws IOException
*/
private void setRandomAccessFile(int length) throws IOException {
try {
RandomAccessFile randomAccessFile=new RandomAccessFile(filePath,"rw");
randomAccessFile.setLength(length);
randomAccessFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获得下载线程,为下一步阻塞做准备
* @param conn 连接
* @param length 长度
* @return
*/
private List<DownloadThread> getDownloadThreads(Connection conn, int length) {
int startPos;
int endPos;
List<DownloadThread> list=new ArrayList<DownloadThread>();
for (int i = 0; i < threadNum; i++) {
//从0开始
startPos=i*(length/threadNum);
//从length/threadNum开始,最后为所有长度
endPos=(i==threadNum-1)?length-1:(i+1)*(length/threadNum);
DownloadThread downloadThread=new DownloadThread(conn,startPos,endPos);
downloadThread.start();
list.add(downloadThread);
}
return list;
}
/**
* 阻塞线程列表,等待线程列表全部执行完成
* @param list 线程列表
*/
private void waitForDownLoad(List<DownloadThread> list) {
for (DownloadThread aList : list) {
try {
aList.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}