HttpURLConnection 多线程下载

 


影响下载的速度

* 宽带的带宽

* 服务器的限制

* 服务器的资源固定,开启的线程越多抢占的资源就越多

import java.io.InputStream;

import java.io.RandomAccessFile;

import java.net.HttpURLConnection;

import java.net.URL;

public class MultiDownLoad {

   static String path = http://192.168.3.100:8080/web/download/gui.exe;
   static int threadCount = 3;

   /**
    * 获取文件的存储路径
    */

   static String getFilePath(){

      int index = path.lastIndexOf("/")+1;

      return "D:\"+path.substring(index);

   }
   public static void main(String[] args) {

      try {
         // 1. 在客户端创建和服务器资源一样大小的空文件

         URL url = new URL(path);

         HttpURLConnection conn = (HttpURLConnection) url.openConnection();

         conn.setConnectTimeout(3000);

         conn.setRequestMethod("GET");

         int code = conn.getResponseCode();

         //服务器资源文件的大小

         int fileLength = 0;

         if (code == 200) {

            fileLength = conn.getContentLength();

            System.out.println("文件大小:"+fileLength);
        
//          //可选,可以不写,检测硬盘的空间够不够用

//          RandomAccessFile raf = new RandomAccessFile(getFilePath(), "rw");

//          //在硬盘上创建控件

//          raf.setLength(fileLength);

//          raf.close();

         }

         //每个线程下载的区块大小

         int blockSize  = fileLength / threadCount;
      
         // 2. 客户端开启多个线程去下载服务器的资源

         for (int threadId = 0; threadId < threadCount; threadId++) {

            int startIndex = threadId * blockSize;

            int endIndex = (threadId + 1)* blockSize -1;

            //最后一个线程,修正下载的结束位置

            if (threadId == threadCount-1) {

                endIndex = fileLength - 1;

            }
           
            //开启线程

            new DownLoadThread(startIndex, endIndex, threadId).start();

         }

      } catch (Exception e) {

         e.printStackTrace();

      }

   }
   
   static class DownLoadThread extends Thread {

      //开始位置

      int startIndex;

      //结束位置

      int endIndex;

      //线程ID

      int threadId;

      public DownLoadThread(int startIndex, int endIndex, int threadId) {

         super();

         this.startIndex = startIndex;

         this.endIndex = endIndex;

         this.threadId = threadId;

      }

      @Override

      public void run() {

         super.run();

         System.out.println("线程 : "+  threadId + " : "+ startIndex+" ~ "+endIndex);

         try {

            URL url = new URL(path);

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            conn.setRequestMethod("GET");

            conn.setConnectTimeout(3000);

            //重要,设置请求的范围

            conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);

            //部分请求成功 206

            int code = conn.getResponseCode();

            System.out.println(" code = "+code);

            if (code == 206) {

                RandomAccessFile raf = new RandomAccessFile(getFilePath(), "rw");

                //重要,写文件之前定位

                raf.seek(startIndex);
             
                //获取这个线程对应的一块资源

                InputStream is = conn.getInputStream();

                byte[] buffer = new byte[1024*8];

                int len = -1;
              
                while((len = is.read(buffer)) != -1){
                 
                   raf.write(buffer, 0, len);

                }
              
                raf.close();
            }
         
            // 3. 每个线程都下载完毕,整个资源就下载完了

            System.out.println("线程 "+threadId+" 干完活了!");

         } catch (Exception e) {

            e.printStackTrace();

         }

      }

   }

}
原文地址:https://www.cnblogs.com/loaderman/p/6432469.html