使用多线程下载文件可以更快的完成文件的下载,多线程下载之所以快,是因为其抢占的服务器资源多。
多线程下载实现的过程:
1,首先得到下载文件的长度,然后设置本地文件的长度
HttpURLConnection.getContentLength();
RandomAccessFile file=new RandowAccessFile("qq.exe","rwd");
file.setLength(filesize);//设置本地文件的长度
2,根据文件长度和线程数计算每条线程下载的数据长度和下载位置
3,使用Http的Range字段指定每条线程从文件的什么位置下载,下载到什么位置
HttpURLConnection.setRequestProperty("Range","byte=500-20000");
4,保存文件,使用RandomAccessFile类指定每条线程从本地文件的什么位置开始写入数据
RandomAccessFile file=new RandowAccessFile("qq.exe","rwd");
file.seek(500);//设置从文件的什么位置开始写入数据
public class FileDownLoader {
@Test
public void download() throws Exception {
String path = "http://www.qq.com/qq.exe";
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5*1000);
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Charset", "UTF-8");
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
conn.setRequestProperty("Connection", "Keep-Alive");
System.out.println(conn.getResponseCode());
int filesize = conn.getContentLength();//得到文件大小
conn.disconnect();
int threasize = 3;//线程数
int perthreadsize = filesize / 3 + 1;
RandomAccessFile file = new RandomAccessFile("102.wma","rw");
file.setLength(filesize);//设置本地文件的大小
file.close();
for(int i=0; i<threasize ; i++){
int startpos = i * perthreadsize;//计算每条线程的下载位置
RandomAccessFile perthreadfile = new RandomAccessFile("102.wma","rw");//
perthreadfile.seek(startpos);//从文件的什么位置开始写入数据
new DownladerThread(i, path, startpos, perthreadsize, perthreadfile).start();
}
//以下代码要求用户输入q才会退出测试方法,如果没有下面代码,会因为进程结束而导致进程内的下载线程被销毁
int quit = System.in.read();
while('q'!=quit){
Thread.sleep(2 * 1000);
}
}
private class DownladerThread extends Thread{
private int startpos;//从文件的什么位置开始下载
private int perthreadsize;//每条线程需要下载的文件大小
private String path;
private RandomAccessFile file;
private int threadid;
public DownladerThread(int threadid, String path, int startpos, int perthreadsize, RandomAccessFile perthreadfile) {
this.path = path;
this.startpos = startpos;
this.perthreadsize = perthreadsize;
this.file = perthreadfile;
this.threadid = threadid;
}
@Override
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setConnectTimeout(5 * 1000);
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Charset", "UTF-8");
conn.setRequestProperty("Range", "bytes=" + this.startpos + "-");
InputStream inStream = conn.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
int length = 0;
while(length<perthreadsize && (len = inStream.read(buffer))!=-1){
file.write(buffer, 0, len);
length += len;//累计该线程下载的总大小
}
file.close();
inStream.close();
System.out.println(threadid+ "线程完成下载");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}