版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ITzhongzi/article/details/88389805
原理解析: 在开启多个线程下载文件的同时,将下载的进度保存在一个临时文件里,每次运行程序查看有没有临时文件,有的话就取临时文件中的进度继续下载。
多线程下载的原理 见上一篇 博客
。
示例demo
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
public class MutilDownload {
private static String path = "http://192.168.80.85:8080/test.pdf";
private static final int threadCount = 3;
private static int runningThread; //标识 正在运行的线程数量
public static void main(String[] args) {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
int responseCode = conn.getResponseCode();
if (responseCode == 200) {
int contentLength = conn.getContentLength();
runningThread = threadCount;
System.out.println("length" + contentLength);
RandomAccessFile rafAccessFile = new RandomAccessFile("test.pdf", "rw");
rafAccessFile.setLength(contentLength);
int blockSize = contentLength / threadCount;
for (int i = 0; i < threadCount; i++) {
int startIndex = i * blockSize; //每个现成下载的开始位置
int endIndex = (i + 1) * blockSize - 1;// 每个线程的结束位置
if (i == threadCount - 1) {
//最后一个线程
endIndex = contentLength - 1;
}
new DownloadThread(startIndex, endIndex, i).start();
}
}
} catch (Exception e) {
}
}
private static class DownloadThread extends Thread {
private int startIndex;
private int endIndex;
private int threadId;
public DownloadThread(int startIndex, int endIndex, int threadId) {
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
}
@Override
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
File file = new File(threadId + ".txt");
if(file.exists() && file.length() > 0) {
FileInputStream fis = new FileInputStream(file);
BufferedReader buff = new BufferedReader(new InputStreamReader(fis));
String lastPosition = buff.readLine();// 读取出来的内容就是上次下载的位置
int lastPos = Integer.parseInt(lastPosition);
System.out.println("线程id:" + threadId + "当前线程下载的位置:-----"+ lastPos);
startIndex = lastPos;
fis.close();
buff.close();
}
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); //固定写法,请求部分资源
int responseCode = conn.getResponseCode(); // 206表示请求部分资源
if (responseCode == 206) {
RandomAccessFile rafAccessFile = new RandomAccessFile("test.pdf", "rw");
rafAccessFile.seek(startIndex);
InputStream is = conn.getInputStream();
int len = -1;
byte[] buffer = new byte[1024];
int total = 0; // 代表当前线程下载的大小
while ((len = is.read(buffer)) != -1) {
rafAccessFile.write(buffer, 0, len);
total += len;
//断点续传, 保存当前线程下载的位置
int currentThreadPosition = startIndex + total; //当前线程下载的位置
// 存储当线程的下载五位置
RandomAccessFile raff = new RandomAccessFile(threadId +".txt", "rwd");
raff.write(String.valueOf(currentThreadPosition).getBytes());
raff.close();
}
rafAccessFile.close();
System.out.println("线程" + threadId + "下载完成");
//删除临时文件
// File tempFile = new File(threadId + ".txt");
// if(tempFile.exists()) {
// file.delete();
// }
synchronized (MutilDownload.class) {
runningThread--;
if(runningThread == 0) {
for (int i = 0; i < threadCount; i++) {
File deleteFile = new File(i + ".txt");
deleteFile.delete();
}
}
}
}
} catch (Exception e) {
}
}
}
}