import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
public class MultiDownload {
private static String path = "Http://192.168.221.221:8080/web/e.exe";
private static int threadCount = 7;// 下载的线程的个数
private static int livingThread = 0;// 记住活着的线程-还在下载的线程
public static void main(String[] args) throws IOException {
URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
int code = connection.getResponseCode();
System.out.println("1:服务器返回状态码:" + code);
if (code == 200) {
// 1、服务器文件的长度
int contentLength = connection.getContentLength();
System.out.println("文件的总长度:" + contentLength);
//2、每一个线程下载的大小
int blockSize = contentLength/threadCount;
System.out.println("每个线程下载的大小blockSize:" + blockSize);
for (int i = 1; i <= threadCount; i++) {
// 3、每一个线程的起始位置和结束位置
int startIndex = (i - 1) * blockSize;
int endIndex = i * blockSize - 1;
if (i == threadCount) {
endIndex = contentLength;// 4、最后一个结束位置为文件末尾
}
livingThread = threadCount;
// 5、开启线程下载文件
new Thread(new DownloadTask(i, startIndex, endIndex)).start();
}
}
}
/**
* 根据路径获取文件名
*
* @param filepath 文件的路径
* @return 文件名
*/
public static String getFileName(String filepath) {
return filepath.substring(filepath.lastIndexOf("/") + 1);
}
/**
*
* 线程下载类
*
* @author hacket
*
*/
private static class DownloadTask implements Runnable {
private int id;// 线程id
private int startIndex;// 下载起始位置
private int endIndex;// 下载结束位置
public DownloadTask(int id, int startIndex, int endIndex) {
this.id = id;
this.startIndex = startIndex;
this.endIndex = endIndex;
}
@Override
public void run() {
try {
// 一、开启一个http连接
URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
// 五、在每次下载之前,检查是否存在已经下载大小记录的文件
File f = new File(getFileName(path) + id + ".txt");
if (f.exists() && f.length() > 0) {// 文件存在
BufferedReader br = new BufferedReader(new FileReader(f));
String total = br.readLine();
startIndex += Integer.parseInt(total);
br.close();
}
System.out.println("线程id:"+id+"下载位置:"+startIndex+"——"+endIndex);
// 二、创建一个随机访问文件
RandomAccessFile raf = new RandomAccessFile(getFileName(path), "rwd");
raf.setLength(connection.getContentLength());// 设置文件总长度
raf.seek(startIndex);// 设置每个线程下载文件的开始位置
// 三、获取输入流开启文件的下载
InputStream in = connection.getInputStream();
int len = 0;
byte[] buf = new byte[1024];
int total = 0;// 记录当前线程下载文件的大小
while ((len = in.read(buf)) != -1) {
// 四、记录当前线程下载的大小
File file = new File(getFileName(path) + id + ".txt");
raf.write(buf, 0, len);
RandomAccessFile positionAccessFile = new RandomAccessFile(file, "rwd");
total += len;
// 将当前下载的大小保存到一个文件中去
positionAccessFile.write(String.valueOf(total).getBytes());
positionAccessFile.close();
}
raf.close();
in.close();
System.out.println("线程:" + id + "下载完毕。。。");
} catch (IOException e) {
e.printStackTrace();
}finally{
synchronized (DownloadTask.class) {
livingThread--;
System.out.println("livingThread:" + livingThread);
if (livingThread <= 0) {
System.out.println("全部下载完毕");
// 六、下载完毕后,将记录文件给删除
for (int i = 1; i <= threadCount; i++) {
File deletFile = new File(getFileName(path) + i
+ ".txt");
System.out.println(i+"删除:"+deletFile.delete());
}
}
}
}
}
}
}