网上类似的文章很多,参考了很多人的,大部分人都是用urlconnection写的。
1、发送一个含有rang头的head请求,如果返回状态码为206,则允许多线程下载
1、使用httpclient的head请求获取请求文件的信息
2、发送一个rang的head请求判断是否允许多线程下载
3、通过主任务创建多个分段下载线程,分段下载文件,然后用java的随机读写文件类保存下载的内容
(等有时间了再添加内容吧,先简单写这么多)
java代码
/**
* 开始下载
* @throws exception
*/
public void startdown() throws exception{
httpclient httpclient = new defaulthttpclient();
try {
//获取下载文件信息
getdownloadfileinfo(httpclient);
//启动多个下载线程
startdownloadthread();
//开始监视下载数据
monitor();
} catch (exception e) {
throw e;
} finally {
httpclient.getconnectionmanager().shutdown();
}
}
* 获取下载文件信息
private void getdownloadfileinfo(httpclient httpclient) throws ioexception,
clientprotocolexception, exception {
httphead httphead = new httphead(url);
httpresponse response = httpclient.execute(httphead);
//获取http状态码
int statuscode = response.getstatusline().getstatuscode();
if(statuscode != 200) throw new exception("资源不存在!");
if(getdebug()){
for(header header : response.getallheaders()){
system.out.println(header.getname()+":"+header.getvalue());
}
//content-length
header[] headers = response.getheaders("content-length");
if(headers.length > 0)
contentlength = long.valueof(headers[0].getvalue());
httphead.abort();
httphead = new httphead(url);
httphead.addheader("range", "bytes=0-"+(contentlength-1));
response = httpclient.execute(httphead);
if(response.getstatusline().getstatuscode() == 206){
acceptranges = true;
* 启动多个下载线程
* @throws ioexception
* @throws filenotfoundexception
private void startdownloadthread() throws ioexception,
filenotfoundexception {
//创建下载文件
file file = new file(localpath);
file.createnewfile();
randomaccessfile raf = new randomaccessfile(file, "rw");
raf.setlength(contentlength);
raf.close();
//定义下载线程事件实现类
downloadthreadlistener listener = new downloadthreadlistener() {
public void afterperdown(downloadthreadevent event) {
//下载完一个片段后追加已下载字节数
synchronized (object) {
downloadtask.this.receivedcount += event.getcount();
}
public void downcompleted(downloadthreadevent event) {
//下载线程执行完毕后从主任务中移除
threads.remove(event.gettarget());
if(getdebug()){
system.out.println("剩余线程数:"+threads.size());
};
//不支持多线程下载时
if (!acceptranges) {
if(getdebug()){
system.out.println("该地址不支持多线程下载");
//定义普通下载
downloadthread thread = new downloadthread(url, 0, contentlength, file, false);
thread.adddownloadlistener(listener);
thread.start();
threads.add(thread);
return;
//每个请求的大小
long perthreadlength = contentlength / threadcount + 1;
long startposition = 0;
long endposition = perthreadlength;
//循环创建多个下载线程
do{
if(endposition >= contentlength)
endposition = contentlength - 1;
downloadthread thread = new downloadthread(url, startposition, endposition, file);
startposition = endposition + 1;//此处加 1,从结束位置的下一个地方开始请求
endposition += perthreadlength;
} while (startposition < contentlength);
}

* 现在过程代码
public void run() {
if(downloadtask.getdebug()){
system.out.println("start:" + startposition + "-" +endposition);
httpget httpget = new httpget(url);
if(isrange){//多线程下载
httpget.addheader("range", "bytes="+startposition+"-"+endposition);
httpresponse response = httpclient.execute(httpget);
int statuscode = response.getstatusline().getstatuscode();
if(downloadtask.getdebug()){
for(header header : response.getallheaders()){
system.out.println(header.getname()+":"+header.getvalue());
system.out.println("statuscode:" + statuscode);
if(statuscode == 206 || (statuscode == 200 && !isrange)){
inputstream inputstream = response.getentity().getcontent();
//创建随机读写类
randomaccessfile outputstream = new randomaccessfile(file, "rw");
//跳到指定位置
outputstream.seek(startposition);
int count = 0;byte[] buffer=new byte[1024];
while((count = inputstream.read(buffer, 0, buffer.length))>0){
outputstream.write(buffer, 0, count);
//触发下载事件
fireafterperdown(new downloadthreadevent(this,count));
outputstream.close();
httpget.abort();
e.printstacktrace();
//触发下载完成事件
firedowncompleted(new downloadthreadevent(this, endposition));
system.out.println("end:" + startposition + "-" +endposition);
1、download.jar为编译好的可运行程序
2、download.zip为eclipse项目文件
3、运行截图
download.jar (928.1 kb)
下载次数: 44
download.zip (832.5 kb)
下载次数: 70