package cn.com.sinosoft.sfjy.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.Set;
public class DonwloadUtil {
public static Map<FileName, DownloadVo> map;
public DonwloadUtil(Map<FileName, DownloadVo> map) {
DonwloadUtil.map = map;
being();
}
public void being() {
System.out.println("++++++++++++++++++++++++++++++++++++++++++++");
Set<FileName> keySet = map.keySet();
for (FileName fileName : keySet) {
map.get(fileName).setFinished(donwload(fileName));
}
System.out.println("++++++++++++++++++++++++++++++++++++++++++++");
}
public boolean donwload(FileName filename) {
// 发送get请求,请求这个地址的资源
try {
// 构建请求路径
URL url = new URL(DonwloadUtil.map.get(filename).getDonwloadPath());
// 发送连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 请求方式
conn.setRequestMethod("GET");
// 请求连接超时
conn.setConnectTimeout(5000);
// 连接中超时
conn.setReadTimeout(5000);
// 请求连接成功 200
if (conn.getResponseCode() == 200) {
// 拿到所请求资源文件的长度
long length = conn.getContentLength();
File file = new File(DonwloadUtil.map.get(filename).getTargetPath() + "/"
+ DonwloadUtil.map.get(filename).getFileName());
// 生成临时文件
RandomAccessFile raf = new RandomAccessFile(file, "rwd");
// 设置临时文件的大小
raf.setLength(length);
raf.close();
// 计算出每个线程应该下载多少字节
long size = length / DonwloadUtil.map.get(filename).getThreadCount();
for (int i = 0; i < DonwloadUtil.map.get(filename).getThreadCount(); i++) {
// 计算线程下载的开始位置和结束位置
long startIndex = i * size;
long endIndex = (i + 1) * size - 1;
// 如果是最后一个线程,那么结束位置写死
if (i == DonwloadUtil.map.get(filename).getThreadCount() - 1) {
endIndex = length - 1;
}
System.out.println(filename+"线程" + i + "的下载区间是:" + startIndex + "---" + endIndex);
new DownLoadThread(startIndex, endIndex, i, filename).start();
}
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
class DownLoadThread extends Thread {
long startIndex;
long endIndex;
int threadId;
FileName filename;
public DownLoadThread(long startIndex, long endIndex, int threadId, FileName filename) {
super();
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
this.filename = filename;
}
@Override
public void run() {
try {
// 存放当前线程的下载进度文件
File progressFile = new File(filename+""+threadId + ".txt");
// 判断进度临时文件是否存在
if (progressFile.exists()) {
FileInputStream fis = new FileInputStream(progressFile);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
// 从进度临时文件中读取出上一次下载的总进度,然后与原本的开始位置相加,得到新的开始位置
startIndex += Integer.parseInt(br.readLine());
fis.close();
}
// System.out.println("线程" + threadId + "的下载区间是:" + startIndex +
// "---" + endIndex);
// 再次发送http请求,下载原文件
HttpURLConnection conn;
URL url = new URL(DonwloadUtil.map.get(filename).getDonwloadPath());
// 发送连接
conn = (HttpURLConnection) url.openConnection();
// 请求方式
conn.setRequestMethod("GET");
// 请求连接超时
conn.setConnectTimeout(5000);
// 连接中超时
conn.setReadTimeout(5000);
// 设置本次http请求所请求的数据的区间
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
//System.out.println(filenaem+conn.getResponseCode());
// 请求部分数据,相应码是206
if (conn.getResponseCode() == 206) {
// 流里此时只有1/3原文件的数据
InputStream is = conn.getInputStream();
byte[] b = new byte[1024];
int len = 0;
int total = 0;
// 拿到临时文件的输出流
File file = new File(DonwloadUtil.map.get(filename).getTargetPath() + "/"
+ DonwloadUtil.map.get(filename).getFileName());
// 生成临时文件
RandomAccessFile raf = new RandomAccessFile(file, "rwd");
// 把文件的写入位置移动至startIndex
raf.seek(startIndex);
while ((len = is.read(b)) != -1) {
// 每次读取流里数据之后,同步把数据写入临时文件
raf.write(b, 0, len);
total += len;
System.out.println(filename+"线程" + threadId + "下载了" + total);
// 生成一个专门用来记录下载进度的临时文件
RandomAccessFile progressRaf = new RandomAccessFile(progressFile, "rwd");
// 每次读取流里数据之后,同步把当前线程下载的总进度写入进度临时文件中
progressRaf.write((total + "").getBytes());
progressRaf.close();
}
System.out.println(filename+"线程" + threadId + "下载完毕!");
raf.close();
DonwloadUtil.map.get(filename)
.setFinishedThread(DonwloadUtil.map.get(filename).getFinishedThread() + 1);
synchronized (DonwloadUtil.map.get(filename).getDonwloadPath()) {
if (DonwloadUtil.map.get(filename).getFinishedThread() == DonwloadUtil.map.get(filename)
.getThreadCount()) {
for (int i = 0; i < DonwloadUtil.map.get(filename).getThreadCount(); i++) {
File f = new File(filename+""+i+ ".txt");
f.delete();
}
DonwloadUtil.map.get(filename).setFinishedThread(0);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}