原帖:http://zywang.iteye.com/blog/916489
网上类似的文章很多,参考了很多人的,大部分人都是用URLConnection写的。
原理一:HTTP多线程下载原理
1、发送一个含有Rang头的Head请求,如果返回状态码为206,则允许多线程下载
原理二:多线程下载原理
1、使用HttpClient的Head请求获取请求文件的信息
2、发送一个Rang的Head请求判断是否允许多线程下载
3、通过主任务创建多个分段下载线程,分段下载文件,然后用Java的随机读写文件类保存下载的内容
(等有时间了再添加内容吧,先简单写这么多)
调度功能代码片段
Java代码 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(); } 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 = newDownloadThreadListener() { public voidafterPerDown(DownloadThreadEvent event) { //下载完一个片段后追加已下载字节数synchronized (object) { DownloadTask.this.receivedCount +=event.getCount(); } } public void downCompleted(DownloadThreadEventevent) { //下载线程执行完毕后从主任务中移除 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; longendPosition = 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); }" quality="high"allowscriptaccess="always" type="application/x-shockwave-flash"pluginspage="http://www.macromedia.com/go/getflashplayer">- publicvoidstartDown()throwsException{
- HttpClienthttpClient=newDefaultHttpClient();
- try{
- //获取下载文件信息
- getDownloadFileInfo(httpClient);
- //启动多个下载线程
- startDownloadThread();
- //开始监视下载数据
- monitor();
- }catch(Exceptione){
- throwe;
- }finally{
- httpClient.getConnectionManager().shutdown();
- }
- }
- privatevoidgetDownloadFileInfo(HttpClienthttpClient)throwsIOException,
- ClientProtocolException,Exception{
- HttpHeadhttpHead=newHttpHead(url);
- HttpResponseresponse=httpClient.execute(httpHead);
- //获取HTTP状态码
- intstatusCode=response.getStatusLine().getStatusCode();
- if(statusCode!=200)thrownewException("资源不存在!");
- if(getDebug()){
- for(Headerheader: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=newHttpHead(url);
- httpHead.addHeader("Range","bytes=0-"+(contentLength-1));
- response=httpClient.execute(httpHead);
- if(response.getStatusLine().getStatusCode()==206){
- acceptRanges=true;
- }
- httpHead.abort();
- }
- privatevoidstartDownloadThread()throwsIOException,
- FileNotFoundException{
- //创建下载文件
- Filefile=newFile(localPath);
- file.createNewFile();
- RandomAccessFileraf=newRandomAccessFile(file,"rw");
- raf.setLength(contentLength);
- raf.close();
- //定义下载线程事件实现类
- DownloadThreadListenerlistener=newDownloadThreadListener(){
- publicvoidafterPerDown(DownloadThreadEventevent){
- //下载完一个片段后追加已下载字节数
- synchronized(object){
- DownloadTask.this.receivedCount+=event.getCount();
- }
- }
- publicvoiddownCompleted(DownloadThreadEventevent){
- //下载线程执行完毕后从主任务中移除
- threads.remove(event.getTarget());
- if(getDebug()){
- System.out.println("剩余线程数:"+threads.size());
- }
- }
- };
- //不支持多线程下载时
- if(!acceptRanges){
- if(getDebug()){
- System.out.println("该地址不支持多线程下载");
- }
- //定义普通下载
- DownloadThreadthread=newDownloadThread(url,0,contentLength,file,false);
- thread.addDownloadListener(listener);
- thread.start();
- threads.add(thread);
- return;
- }
- //每个请求的大小
- longperThreadLength=contentLength/threadCount+1;
- longstartPosition=0;
- longendPosition=perThreadLength;
- //循环创建多个下载线程
- do{
- if(endPosition>=contentLength)
- endPosition=contentLength-1;
- DownloadThreadthread=newDownloadThread(url,startPosition,endPosition,file);
- thread.addDownloadListener(listener);
- thread.start();
- threads.add(thread);
- startPosition=endPosition+1;//此处加1,从结束位置的下一个地方开始请求
- endPosition+=perThreadLength;
- }while(startPosition<contentLength);
- }