网上类似的文章很多,参考了很多人的,大部分人都是用URLConnection写的。
1、发送一个含有Rang头的Head请求,如果返回状态码为206,则允许多线程下载
1、使用HttpClient的Head请求获取请求文件的信息
2、发送一个Rang的Head请求判断是否允许多线程下载
3、通过主任务创建多个分段下载线程,分段下载文件,然后用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; } 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); }
/** * 现在过程代码 */ 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(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(); } catch (Exception e) { e.printStackTrace(); } finally { //触发下载完成事件 fireDownCompleted(new DownloadThreadEvent(this, endPosition)); if(DownloadTask.getDebug()){ System.out.println("End:" + startPosition + "-" +endPosition); } httpClient.getConnectionManager().shutdown(); } }
1、Download.jar为编译好的可运行程序
2、Download.zip为Eclipse项目文件