好久没有更新博客了 ,今天写了一篇多线程下载并可以实现暂停之后继续下载,文章还有很多改进的地方, 望大神们不吝赐教
package mutildownload1;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* HttpURLConnection 使用步骤
* A:URl url=new URL() 将字符串变为java程序可以识别的url地址
* B:HttpURLConnection con=(HttpURLConnection)url.openConection() 打开一个HttpURLConnection 的链接
* C:con.setRequestMethod();设置请求方式 GET或POST
* D:con.setConnectTimeout();设置允许多长时间没反应
* E:con.getResponseCode();获取求状态码 200 获取整个文件成功 206 获取部分文件成功
*
*/
public class MutilDownload2 {
/**
* 多线程下载(可以实现断点续传)
* 实现思路:
* (多线程下载)
* A:获取文件总大小 con.getContentLength()
* B:将获取到的大小按照你准备的线程数进行分配 并计算出每个线程下载的起始位置
* C:开启多个线程下载
* D:因为是多线程下载 所以得设置好每个线程真正下载的起始位置(这是一句死的 照写就行)
* con.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
*
* (断点续传)
* E:在读取文件的时候可能出现中断 这个时候我们需要把当前线程下载到哪儿了的位置记住,并写进以当前线程为名字的.txt文件中
* F:在进入每个线程下载之前 先去文件读一读 有没有以线程名+.txt的文件存在,
* 如果存在并且文件大于0,就把文件中存储的线程位置读出来,并赋值给当前线程的开始位置,然后继续下载
*
*/
private static final String path = "http://172.24.48.43:8080/2.exe";
private static final int ThreadIdcount = 3;
public static void main(String args[]) {
try {
URL url = new URL(path);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setConnectTimeout(5000);
int code = con.getResponseCode();
if (code == 200) {
int length = con.getContentLength();//取得要下载文件的总大小
int blockSize = length / ThreadIdcount;//计算出每个线程应该下载多少
for (int i = 0; i < ThreadIdcount; i++) {//计算出每个线程下载的起始位置和结束位置
int startIndex = i * blockSize;
int endIndex = (i + 1) * blockSize;
if (i == ThreadIdcount - 1) {//最后一个线程就多下载点
endIndex = length - 1;
}
DownloadThread thread = new DownloadThread(startIndex, endIndex, i);
new Thread(thread).start();//开启多个线程下载
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static class DownloadThread implements Runnable {
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 con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setConnectTimeout(5000);
File file=new File(threadId+".txt");
if(file.exists()&&file.length()>0){
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = reader.readLine();
int lastPostion = Integer.parseInt(line);
startIndex=lastPostion+1;
}
//设置每个线程真正下载的开始和结束位置
con.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
int code = con.getResponseCode();
int total = 0;
if (code == 206) {//206代表获取部分资源成功. 这里是线程下载,所以状态码用206
//这里使用RandomAccessFile类的目的在于 可以指定文件写入的位置
RandomAccessFile rw = new RandomAccessFile("sql.exe", "rw");
//指定文件写入的位置
rw.seek(startIndex);
InputStream in = con.getInputStream();
int len = -1;
byte[] bs = new byte[1024 * 1024];
while (-1 != (len = in.read(bs))) {
total += len;
int currentPostionToatal = startIndex + total;//当前线程的大小
RandomAccessFile rff= new RandomAccessFile(threadId + ".txt","rwd");
rff.write(String.valueOf(currentPostionToatal).getBytes());
rw.write(bs, 0, len);
rff.close();
}
rw.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}