一、多线程下载:
1.使用HttpURLConnection来实现多线程下载。
①通过服务器资源路径来得到URL。
②通过URL得到HttpURLConnection对象,并且设置发送请求方式和请求参数等。
③得到资源文件的大小和线程个数,创建一个相同大小的RandomAccessFile文件。
④ 得到每个线程需要下载的区块大小,计算每个线程对应的下载的位置(startIndex~endIndex)。
⑤创建并开启线程。
2.多线程下载的细节。
①从服务器下载的资源都是从0开始至size-1。
②从服务器下载一部分资源返回的响应码是206。
③必须设置该请求参数:
conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
④RandomAccessFile的seek(int count)方法代表从指定的位置开始写入。
3.多线程下载功能实现代码:
public class MultiThreadDownload {
conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
/**
* 下载资源的路径
*/
private String sourcePath;
/**
* 下载资源的文件保存路径
*/
private String filePath;
/**
* 线程的个数
*/
private int threadCount;
/**
* 每个线程下载的区块大小
*/
private long blockSize;
public MultiThreadDownload(String sourcePath, String filePath, int threadCount) {
this.sourcePath = sourcePath;
this.filePath = filePath;
this.threadCount = threadCount;
}
/**
* 下载
* @throws Exception
*/
public void downLoad() throws Exception{
URL url =new URL(sourcePath);
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
//发送GET请求
conn.setRequestMethod("GET");
//设置连接超时时长
conn.setConnectTimeout(5*1000);
//获取服务器响应码
int code=conn.getResponseCode();
if(code==200){
//得到资源总大小
int size=conn.getContentLength();
//创建一个随机访问的可读写文件
RandomAccessFile file=new RandomAccessFile(filePath, "rw");
//设置该文件大小
file.setLength(size);
blockSize=size/threadCount;
//计算每个线程的下载起始位置与终止位置
for(int i=1;i<=threadCount;i++){
long startIndex =(i-1)*blockSize; //线程下载的开始位置
long endIndex=i*blockSize-1; //线程下载的结束位置
if(i==threadCount){
endIndex=size-1;
}
//创建并开启线程
new DownThread(startIndex, endIndex, i).start();
}
}
//释放连接
conn.disconnect();
}
/**
* 线程下载类
*
*/
private class DownThread extends Thread{
/**
* 线程下载开始位置
*/
private long startIndex;
/**
* 线程下载结束位置
*/
private long endIndex;
/**
* 线程的ID
*/
private int threadId;
public DownThread(long startIndex, long endIndex, int threadId) {
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
}
@Override
public void run() {
try {
URL url =new URL(sourcePath);
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
//必须设置该请求参数
conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
conn.setConnectTimeout(5*1000);
//下载服务器一部分资源获得的响应码是206
int code=conn.getResponseCode();
if(code==206){
//得到输入流
InputStream is=conn.getInputStream();
RandomAccessFile raf=new RandomAccessFile(filePath, "rw");
//从指定位置开始写入
raf.seek(startIndex);
int len=0;
byte [] buffer=new byte[1024];
while((len=is.read(buffer))!=-1){
raf.write(buffer,0,len);
}
raf.close();
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
System.out.println("线程"+threadId+"下载完毕了!");
}
}
}
}