说明:
生成多个线程去服务器下载文件,服务器几乎同一时间处理每个线程,这样就会更快的下好文件,但注意并不是开的线程越多,速度越快。
文件的存储是有序的,必须保证下载的有序性,我们可以对需要下载的文件进行数据分块,这样每次访问的就可以不是完整的文件了。http协议有一个range字段,可以设置数据访问的区域位置,java中有RandomAccessfile类可以我们按需要去读写改某个区域。
代码:
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
public class MutiDownload {
private static String DOWNLOAD_PATH="http://s1.music.126.net/download/osx/NeteaseMusic_1.4.3_452_web.dmg";
private static int THREAD_COUNT=3;
private static final String fileName="/Users/August/Desktop/NeteaseMusic_1.4.3_452_web.dmg";
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
HttpURLConnection connection=(HttpURLConnection) new URL(DOWNLOAD_PATH).openConnection();
//设置参数,发送GET请求
connection.setRequestMethod("GET");
//设置链接网络的超时时间
connection.setConnectTimeout(8000);
//获取返回码
int code =connection.getResponseCode();
if (code==200) {
//代表请求成功
RandomAccessFile raf=new RandomAccessFile(fileName, "rw");
long filesize;
filesize=connection.getContentLength();
long eachsize = filesize/THREAD_COUNT;
raf.setLength(filesize);
raf.close();
for (int i = 0; i < THREAD_COUNT; i++) {
long startIndex=i*eachsize;
long endIndex=(i+1)*eachsize;
if (i==THREAD_COUNT-1) {
endIndex=filesize-1;
}
//开启线程去服务器下载
DownloadThread downloadThread=new DownloadThread(DOWNLOAD_PATH,fileName,i,startIndex,endIndex);
}
}else{
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
}
}
}
class DownloadThread extends Thread{
private String url;
private String fileName;
private int threadId;
private long startIndex;
private long endIndex;
private HttpURLConnection connection;
private RandomAccessFile raf;
private InputStream inputStream;
public DownloadThread(String url,String fileName,int threadId,long startIndex,long endIndex) {
this.endIndex=endIndex;
this.fileName=fileName;
this.startIndex=startIndex;
this.threadId=threadId;
this.url=url;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
connection = (HttpURLConnection) new URL(url + "?ts=" + System.currentTimeMillis()).openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
//告诉服务器每个线程的下载位置与结束位置
connection.setRequestProperty("RANGE", "bytes=" + startIndex + "-" + endIndex);
int code =connection.getResponseCode();
if (code==206) { //200代表请求全部资源成功,206代表请求部分资源成功
inputStream=connection.getInputStream();
raf=new RandomAccessFile(fileName, "rw");
raf.seek(startIndex);//
int len=-1;
long total=0;
byte[]buffer=new byte[1024]; //1kb
while ((len=inputStream.read(buffer))!=-1) {
total+=len;
System.out.println("线程"+threadId+":"+total);
raf.write(buffer,0,len);
}
}
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
try{
if (connection!=null) {
connection.disconnect();
}
if (raf!=null) {
raf.close();
}
if (inputStream!=null) {
inputStream.close();
}
}catch(Exception e2){
e2.printStackTrace();
}
}
}
}