日期:2014-05-16  浏览次数:21062 次

使用Apache HttpClient实现多线程下载的小例子
    <span style="color: #000000;">网上类似的文章很多,参考了很多人的,大部分人都是用urlconnection写的。</span>
<h3><span style="color: #0000ff;">原理一:http多线程下载原理</span></h3>1、发送一个含有rang头的head请求,如果返回状态码为206,则允许多线程下载
?
<h3><span style="color: #0000ff;">原理二:多线程下载原理</span></h3>1、使用httpclient的head请求获取请求文件的信息
2、发送一个rang的head请求判断是否允许多线程下载
3、通过主任务创建多个分段下载线程,分段下载文件,然后用java的随机读写文件类保存下载的内容
?
等有时间了再添加内容吧,先简单写这么多
<h4><span style="color: #ff0000;">调度功能代码片段</span></h4>
	/**	 * 开始下载	 * @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;		}		httphead.abort();	}	/**	 * 启动多个下载线程	 * @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);			thread.adddownloadlistener(listener);			thread.start();			threads.add(thread);			startposition = endposition + 1;//此处加 1,从结束位置的下一个地方开始请求			endposition += perthreadlength;		} while (startposition < contentlength);	}
<h4><span style="color: #ff0000;">?分段下载线程代码片段:</span></h4>
		/**	 * 现在过程代码	 */	public void run() {		if(downloadtask.getdebug()){			system.out.println("start:" + startposition + "-" +endposition);		}		httpclient httpclient = new defaulthttpclient();		try {			httpget httpget = new httpget(url);			if(isrange){//多线程下载				httpget.addheader("range", "bytes="+startposition+"-"+endposition);			}			httpresponse response = httpclient.execute(httpge