java网络编程之Http多线程下载应用实例

文章出处: http://blog.csdn.net/hejiangtao 

本demo通过RandomAccessFile, URLConnection和多线程机制实现了Http下载功能.这里可以下载到完整的java代码工程: http://download.csdn.net/detail/hejiangtao/4029935.  相对于别的网上的例子来看, 本demo是可运行的, 可以判断网络资源是否支持分段下载. 你是否遇到了java下载的图片显示不出来或者RAR解压不了的情况, 可以参考本demo的解决方案偷笑

设计思路:

1. 首先读取文件的长度, 并判断网站是否支持分段下载

2. 如果支持分段下载则创建多个线程同时下载该文件,否则使用单线程下载

3. 在各个线程中,分别使用RandomAccessFile对象写入对应的文件位置

具体实现解析:

      1. 为了方便理解,先把util类贴出来.

SysValue.java:

在实际应用中,这些参数应该可以在界面配置或者配置文件配置.

  1. package com.ross.httpdownload.util;  
  2. /** 
  3.  * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com 
  4.  * Date: 2012-1-18 
  5.  * Since: MyJavaExpert v1.0 
  6.  * Description: 
  7.  */  
  8. public class SysValue  
  9. {  
  10.     //constant values   
  11.     //maximum number of the download thread   
  12.     public static int MAX_Num_Of_Thread = 3;  
  13.     //download file store path   
  14.     public static String Save_As_Path = "E:/myspace/download/";  
  15.     //buffer size   
  16.     public static int Buffer_Size = 1024;      
  17. }  
package com.ross.httpdownload.util;
/**
 * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
 * Date: 2012-1-18
 * Since: MyJavaExpert v1.0
 * Description:
 */
public class SysValue
{
    //constant values
    //maximum number of the download thread
    public static int MAX_Num_Of_Thread = 3;
    //download file store path
    public static String Save_As_Path = "E:/myspace/download/";
    //buffer size
    public static int Buffer_Size = 1024;    
}
HttpProcess.java:

将Http相关的公共操作放在这个类里面,避免写重复代码.

  1. package com.ross.httpdownload.util;  
  2. import java.io.IOException;  
  3. import java.net.*;  
  4. /** 
  5.  * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com 
  6.  * Date: 2012-1-18 
  7.  * Since: MyJavaExpert v1.0 
  8.  * Description: This class will provide the common process of http 
  9.  */  
  10. public class HttpProcess  
  11. {  
  12.     /** 
  13.      * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com 
  14.      * Description: get an object of opened URL connection 
  15.      * @param sURL: completed URL string 
  16.      * @return oHttpURLCon: an object of opened URL connection 
  17.      * @throws IOException 
  18.      */  
  19.     public URLConnection  getURLConnection(String sURL) throws IOException  
  20.     {  
  21.         URLConnection  oURLCon = null;  
  22.         // replace space with '+' in the URL string   
  23.         if (null != sURL)  
  24.         {  
  25.             sURL = sURL.replaceAll("\\s""+");  
  26.             // generate URL   
  27.             URL oURL = new URL(sURL);  
  28.             oURLCon = (URLConnection) oURL.openConnection();  
  29.         }  
  30.         return oURLCon;  
  31.     }  
  32.   
  33. }  
package com.ross.httpdownload.util;
import java.io.IOException;
import java.net.*;
/**
 * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
 * Date: 2012-1-18
 * Since: MyJavaExpert v1.0
 * Description: This class will provide the common process of http
 */
public class HttpProcess
{
    /**
     * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
     * Description: get an object of opened URL connection
     * @param sURL: completed URL string
     * @return oHttpURLCon: an object of opened URL connection
     * @throws IOException
     */
    public URLConnection  getURLConnection(String sURL) throws IOException
    {
        URLConnection  oURLCon = null;
        // replace space with '+' in the URL string
        if (null != sURL)
        {
            sURL = sURL.replaceAll("\\s", "+");
            // generate URL
            URL oURL = new URL(sURL);
            oURLCon = (URLConnection) oURL.openConnection();
        }
        return oURLCon;
    }

}

    2. 看我们的多线程下载实现

a. 首先看下如何判断网站资源是否支持分段下载

很多网络资源,即使在java里面设置了http的InputStream流的范围后, 取的的流的长度还是整个文件的长度. 针对这种情况我就认为该资源不支持分段下载,也就是无法多线程下载了(使用原来的方式下载你就发现下载的图片只能显示一半,或者不能显示,RAR也是损坏的, 字节不对吗 :)). 我也试过通过使用InputStream流的skip方法跳过前面内容的方式实现多线程,但是事实证明,skip太不靠谱,跳的步长并不是一定的,哎什么玩意,只好放弃.

  1. /** 
  2.  * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com 
  3.  * Description: Check whether the server support multiple thread download or not 
  4.  * @param sURL: the download file URL 
  5.  * @return bRet: true - support, false - not support 
  6.  * @throws IOException  
  7.  */  
  8. public boolean isSupportMultipleThreadDown(String sURL) throws IOException  
  9. {  
  10.     boolean bRet = true;  
  11.    // get URL connection   
  12.     URLConnection oURLCon = oHttpProcess.getURLConnection(sURL);  
  13.    // set the resource range   
  14.     oURLCon.setRequestProperty("Range""bytes=" + 0 + "-" + 1023);  
  15.   
  16.     if (1024 < oURLCon.getContentLength())  
  17.     {  
  18.         bRet = false;  
  19.     }  
  20.     return bRet;  
  21. }  
    /**
     * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
     * Description: Check whether the server support multiple thread download or not
     * @param sURL: the download file URL
     * @return bRet: true - support, false - not support
     * @throws IOException 
     */
    public boolean isSupportMultipleThreadDown(String sURL) throws IOException
    {
        boolean bRet = true;
       // get URL connection
        URLConnection oURLCon = oHttpProcess.getURLConnection(sURL);
       // set the resource range
        oURLCon.setRequestProperty("Range", "bytes=" + 0 + "-" + 1023);

        if (1024 < oURLCon.getContentLength())
        {
            bRet = false;
        }
        return bRet;
    }

b. 然后我们看下如何,将文件分段下载

1) 首先是预处理

先是做了个简单的判断,防止线程过多或者小于1; 然后判断网络资源是否支持分段下载,如果不支持则将线程数重置为1; 在获取整个文件长度后, 使用总长度除以线程数得出每个线程负责下载的字节范围.

2) 使用线程池管理并启动多线程下载

DownloadTread就是我们的线程下载实现类, 后面会单独说明. 众所周知java下标是从0开始的,所以各个线程分配字节范围的时候,要考虑进去. 将对应分配的字节范围,URL,文件名信息设置给DownloadTread对象后,使用ExecutorService启动线程.

3)当然不要忘记在finally里面调用线程池的关闭方法.

  1. /** 
  2.  * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com 
  3.  * Description: download tool entry method 
  4.  * @param sURL: the completed URL of the file, which is wanted to download.  
  5.  * @param Num: Number of concurrent download thread 
  6.  * @param sSaveAsName: the the file name saved in disk, like: myphoto.jpg 
  7.  */  
  8. public void download(String sURL, int iNumOfThread, String sSaveAsName)  
  9. {  
  10.     long lFileLen = 0;  
  11.     long lFileSegementLen = 0;  
  12.     long iLeft = 0;  
  13.     URLConnection oURLCon = null;  
  14.     String sFullFileName = SysValue.Save_As_Path + sSaveAsName;  
  15.   
  16.     if (iNumOfThread > SysValue.MAX_Num_Of_Thread)  
  17.     {  
  18.         iNumOfThread = SysValue.MAX_Num_Of_Thread;  
  19.     }  
  20.     if (iNumOfThread < 1)  
  21.     {  
  22.         iNumOfThread = 1;  
  23.     }  
  24.   
  25.     // build the thread pool to manage the thread   
  26.     ExecutorService oExecService = Executors  
  27.             .newFixedThreadPool(iNumOfThread);  
  28.     try  
  29.     {  
  30.         if (!isSupportMultipleThreadDown(sURL))  
  31.         {  
  32.             System.out  
  33.                     .println("This site do not support multiple thread download, reset the thread to 1");  
  34.             iNumOfThread = 1;  
  35.         }  
  36.         // get URL connection   
  37.         oURLCon = oHttpProcess.getURLConnection(sURL);  
  38.         // get the length of the file   
  39.         lFileLen = oURLCon.getContentLength();  
  40.         // split the length of the file according to the number of thread.   
  41.         lFileSegementLen = lFileLen / iNumOfThread;  
  42.         iLeft = lFileLen % iNumOfThread;  
  43.   
  44.         for (int i = 0; i < iNumOfThread; i++)  
  45.         {  
  46.             // initial the thread data   
  47.             DownloadThread oDownloadThread = new DownloadThread();  
  48.             oDownloadThread.setIThreadId(i);  
  49.             // Start index of the current thread   
  50.             oDownloadThread.setLStartIndex(i * lFileSegementLen);  
  51.   
  52.             // last thread will take all the rest content   
  53.             if (i == (iNumOfThread - 1))  
  54.             {  
  55.                 oDownloadThread.setLEndIndex((i + 1) * lFileSegementLen  
  56.                         + iLeft - 1);  
  57.             }  
  58.             else  
  59.             {  
  60.                 oDownloadThread  
  61.                         .setLEndIndex((i + 1) * lFileSegementLen - 1);  
  62.             }  
  63.             // set save file name with path   
  64.             oDownloadThread.setSFullFileName(sFullFileName);  
  65.             // set URL   
  66.             oDownloadThread.setSFileURL(sURL);  
  67.             // execute the download thread   
  68.             oExecService.execute(oDownloadThread);  
  69.         }  
  70.         System.out.println("the file is stored as \"" + sFullFileName  
  71.                 + "\".");  
  72.         System.out.println("the file length is " + lFileLen + ".");  
  73.     }  
  74.     catch (IOException e)  
  75.     {  
  76.         System.out.println("download the file failed, IO Exception"  
  77.                 + e.getMessage());  
  78.         e.printStackTrace();  
  79.     }  
  80.     finally  
  81.     {  
  82.         oExecService.shutdown();  
  83.     }  
  84. }  
    /**
     * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
     * Description: download tool entry method
     * @param sURL: the completed URL of the file, which is wanted to download. 
     * @param Num: Number of concurrent download thread
     * @param sSaveAsName: the the file name saved in disk, like: myphoto.jpg
     */
    public void download(String sURL, int iNumOfThread, String sSaveAsName)
    {
        long lFileLen = 0;
        long lFileSegementLen = 0;
        long iLeft = 0;
        URLConnection oURLCon = null;
        String sFullFileName = SysValue.Save_As_Path + sSaveAsName;

        if (iNumOfThread > SysValue.MAX_Num_Of_Thread)
        {
            iNumOfThread = SysValue.MAX_Num_Of_Thread;
        }
        if (iNumOfThread < 1)
        {
            iNumOfThread = 1;
        }

        // build the thread pool to manage the thread
        ExecutorService oExecService = Executors
                .newFixedThreadPool(iNumOfThread);
        try
        {
            if (!isSupportMultipleThreadDown(sURL))
            {
                System.out
                        .println("This site do not support multiple thread download, reset the thread to 1");
                iNumOfThread = 1;
            }
            // get URL connection
            oURLCon = oHttpProcess.getURLConnection(sURL);
            // get the length of the file
            lFileLen = oURLCon.getContentLength();
            // split the length of the file according to the number of thread.
            lFileSegementLen = lFileLen / iNumOfThread;
            iLeft = lFileLen % iNumOfThread;

            for (int i = 0; i < iNumOfThread; i++)
            {
                // initial the thread data
                DownloadThread oDownloadThread = new DownloadThread();
                oDownloadThread.setIThreadId(i);
                // Start index of the current thread
                oDownloadThread.setLStartIndex(i * lFileSegementLen);

                // last thread will take all the rest content
                if (i == (iNumOfThread - 1))
                {
                    oDownloadThread.setLEndIndex((i + 1) * lFileSegementLen
                            + iLeft - 1);
                }
                else
                {
                    oDownloadThread
                            .setLEndIndex((i + 1) * lFileSegementLen - 1);
                }
                // set save file name with path
                oDownloadThread.setSFullFileName(sFullFileName);
                // set URL
                oDownloadThread.setSFileURL(sURL);
                // execute the download thread
                oExecService.execute(oDownloadThread);
            }
            System.out.println("the file is stored as \"" + sFullFileName
                    + "\".");
            System.out.println("the file length is " + lFileLen + ".");
        }
        catch (IOException e)
        {
            System.out.println("download the file failed, IO Exception"
                    + e.getMessage());
            e.printStackTrace();
        }
        finally
        {
            oExecService.shutdown();
        }
    }

c.最后就是我们的核心下载线程实现类了

1) DownloadTread类实现了Runnalbe抽象接口, 实现了其run()方法.

2) 两个关键的地方一是通过使用URLConnection 的setRequestProperty方法设置本线程读取的流的范围, 另外一个是通过RandomAccessFile 的seek方法或者当前线程写入文件的位置, 一个字节都不能错哦,错了你的文件就有差错了, 还是要记住java下标是从0开始的.

3)然后通过循环从URLConnection的InputStream里面通过buffer一组一组的读出来, 通过RandomAccessFile 对象一组一组的写入到目标文件里面(代码里面判断实际读取长度部分是不需要的, 可以去掉, 是我探索不支持分段下载网络资源的多线程下载方式时留下的).

4)需要提一下的是run()方法是没有输入参数的,所以我们通过增加类字段的方式将参数传入该方法.

  1. package com.ross.httpdownload;  
  2. import java.io.*;  
  3. import java.net.*;  
  4. import java.text.*;  
  5. import java.util.Date;  
  6. import com.ross.httpdownload.util.*;  
  7. /** 
  8.  * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com 
  9.  * Date: 2012-1-18 
  10.  * Since: MyJavaExpert v1.0 
  11.  * Description: download thread implementation. 
  12.  */  
  13. public class DownloadThread implements Runnable  
  14. {  
  15.     private String sFileURL;  
  16.     private long lStartIndex;  
  17.     private long lEndIndex;  
  18.     private int iThreadId;  
  19.     private String sFullFileName;  
  20.     private HttpProcess oHttpProcess;  
  21.     /** 
  22.      * Description: default constructor, it is used for initializing the fields. 
  23.      */  
  24.     public DownloadThread()  
  25.     {  
  26.         oHttpProcess = new HttpProcess();  
  27.     }  
  28.     /** 
  29.      * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com 
  30.      * Description: it will implement the download logic 
  31.      */  
  32.     public void run()  
  33.     {  
  34.         System.out.println("The download thread "  
  35.                 + this.iThreadId  
  36.                 + " is started at "  
  37.                 + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))  
  38.                         .format(new Date()));  
  39.         System.out.println("The download index of " + this.iThreadId + " is "  
  40.                 + this.lStartIndex + " to " + this.lEndIndex);  
  41.   
  42.         // content length   
  43.         long lContentlen = 0;  
  44.         // used to store the new url connection   
  45.         URLConnection oURLCon = null;  
  46.         // used to store the input stream of the response   
  47.         BufferedInputStream oBIn = null;  
  48.         // used to store the output writer   
  49.         RandomAccessFile oRAFile = null;  
  50.         // create the buffer   
  51.         byte[] bBuffer = new byte[SysValue.Buffer_Size];  
  52.   
  53.         // get URL connection   
  54.         try  
  55.         {  
  56.             // create a link for each thread   
  57.             oURLCon = oHttpProcess.getURLConnection(this.sFileURL);  
  58.             // allow the user interaction, for example: a verify pop window   
  59.             oURLCon.setAllowUserInteraction(true);  
  60.             // set the resource range   
  61.             oURLCon.setRequestProperty("Range""bytes=" + this.lStartIndex  
  62.                     + "-" + this.lEndIndex);  
  63.   
  64.             // get the url connection input stream   
  65.             oBIn = new BufferedInputStream(oURLCon.getInputStream());  
  66.    
  67.             // initialize the random access file object   
  68.             oRAFile = new RandomAccessFile(this.sFullFileName, "rw");   
  69.             oRAFile.seek(this.lStartIndex);  
  70.   
  71.             // read the stream from http connection   
  72.             int iLen = 0;  
  73.             int iActualLen = 0;  
  74.             while (iActualLen < (this.lEndIndex - this.lStartIndex + 1))  
  75.             {  
  76.                 iLen = oBIn.read(bBuffer, 0, SysValue.Buffer_Size);  
  77.                 if (-1 == iLen)  
  78.                 {  
  79.                     break;  
  80.                 }  
  81.   
  82.                 // write the read data to file   
  83.                 oRAFile.write(bBuffer, 0, iLen);  
  84.   
  85.                 // move the position mark   
  86.                 iActualLen = iActualLen + iLen;  
  87.             }  
  88.             System.out.println("Thread " + this.iThreadId  
  89.                     + " download is finished, totaly: " + iActualLen);  
  90.         }  
  91.         catch (IOException e)  
  92.         {  
  93.             System.out.println("download the file failed, IO Exception"  
  94.                     + e.getMessage());  
  95.             e.printStackTrace();  
  96.         }  
  97.         finally  
  98.         {  
  99.             if (null != oRAFile)  
  100.             {  
  101.                 try  
  102.                 {  
  103.                     oRAFile.close();  
  104.                 }  
  105.                 catch (IOException e)  
  106.                 {  
  107.                     System.out  
  108.                             .println("close object of RandomAccessFile failed, IO Exception"  
  109.                                     + e.getStackTrace());  
  110.                 }  
  111.             }  
  112.   
  113.             if (null != oBIn)  
  114.             {  
  115.                 try  
  116.                 {  
  117.                     oBIn.close();  
  118.                 }  
  119.                 catch (IOException e)  
  120.                 {  
  121.                     System.out  
  122.                             .println("close input stream of http connection failed, IO Exception"  
  123.                                     + e.getStackTrace());  
  124.                 }  
  125.             }  
  126.         }  
  127.         System.out.println("The download thread "  
  128.                 + this.iThreadId  
  129.                 + " is ended at "  
  130.                 + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))  
  131.                         .format(new Date()));  
  132.     }  
  133.    //省略了set/get方法     
  134. }  
package com.ross.httpdownload;
import java.io.*;
import java.net.*;
import java.text.*;
import java.util.Date;
import com.ross.httpdownload.util.*;
/**
 * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
 * Date: 2012-1-18
 * Since: MyJavaExpert v1.0
 * Description: download thread implementation.
 */
public class DownloadThread implements Runnable
{
    private String sFileURL;
    private long lStartIndex;
    private long lEndIndex;
    private int iThreadId;
    private String sFullFileName;
    private HttpProcess oHttpProcess;
    /**
     * Description: default constructor, it is used for initializing the fields.
     */
    public DownloadThread()
    {
        oHttpProcess = new HttpProcess();
    }
    /**
     * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
     * Description: it will implement the download logic
     */
    public void run()
    {
        System.out.println("The download thread "
                + this.iThreadId
                + " is started at "
                + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
                        .format(new Date()));
        System.out.println("The download index of " + this.iThreadId + " is "
                + this.lStartIndex + " to " + this.lEndIndex);

        // content length
        long lContentlen = 0;
        // used to store the new url connection
        URLConnection oURLCon = null;
        // used to store the input stream of the response
        BufferedInputStream oBIn = null;
        // used to store the output writer
        RandomAccessFile oRAFile = null;
        // create the buffer
        byte[] bBuffer = new byte[SysValue.Buffer_Size];

        // get URL connection
        try
        {
            // create a link for each thread
            oURLCon = oHttpProcess.getURLConnection(this.sFileURL);
            // allow the user interaction, for example: a verify pop window
            oURLCon.setAllowUserInteraction(true);
            // set the resource range
            oURLCon.setRequestProperty("Range", "bytes=" + this.lStartIndex
                    + "-" + this.lEndIndex);

            // get the url connection input stream
            oBIn = new BufferedInputStream(oURLCon.getInputStream());
 
            // initialize the random access file object
            oRAFile = new RandomAccessFile(this.sFullFileName, "rw"); 
            oRAFile.seek(this.lStartIndex);

            // read the stream from http connection
            int iLen = 0;
            int iActualLen = 0;
            while (iActualLen < (this.lEndIndex - this.lStartIndex + 1))
            {
                iLen = oBIn.read(bBuffer, 0, SysValue.Buffer_Size);
                if (-1 == iLen)
                {
                    break;
                }

                // write the read data to file
                oRAFile.write(bBuffer, 0, iLen);

                // move the position mark
                iActualLen = iActualLen + iLen;
            }
            System.out.println("Thread " + this.iThreadId
                    + " download is finished, totaly: " + iActualLen);
        }
        catch (IOException e)
        {
            System.out.println("download the file failed, IO Exception"
                    + e.getMessage());
            e.printStackTrace();
        }
        finally
        {
            if (null != oRAFile)
            {
                try
                {
                    oRAFile.close();
                }
                catch (IOException e)
                {
                    System.out
                            .println("close object of RandomAccessFile failed, IO Exception"
                                    + e.getStackTrace());
                }
            }

            if (null != oBIn)
            {
                try
                {
                    oBIn.close();
                }
                catch (IOException e)
                {
                    System.out
                            .println("close input stream of http connection failed, IO Exception"
                                    + e.getStackTrace());
                }
            }
        }
        System.out.println("The download thread "
                + this.iThreadId
                + " is ended at "
                + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
                        .format(new Date()));
    }
   //省略了set/get方法  
}

来测试下我们的实现:

看下我们的main函数, 我们就通过3个例子来测试我们的实现: 一个可以多线程下载的zip文件,一个可以多线程下载的图片,一个不能多线程下载图片.

MyMain.java:

  1. package com.ross.httpdownload;  
  2. import com.ross.httpdownload.util.*;  
  3. /** 
  4.  * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com 
  5.  * Date: 2012-1-19 
  6.  * Since: MyJavaExpert v1.0 
  7.  * Description: Test the download tool class 
  8.  */  
  9. public class MyMain  
  10. {  
  11.     public static void main(String[] args)  
  12.     {  
  13.         // set system configuration, in real software, it can be configured   
  14.         // through GUI, file,etc.   
  15.         SysValue.MAX_Num_Of_Thread = 3;  
  16.         SysValue.Save_As_Path = "E:/myspace/download/";  
  17.         SysValue.Buffer_Size = 1024;  
  18.         //file web address   
  19.         //String sFileURL = "http://xinsheng-image.huawei.com/cn/forumimage/showimage-991441-20990f56c5b11261fa63e969d8d5580c-self.jpg";   
  20.         //String sFileURL = "http://lh5.googleusercontent.com/-F7a0loCDyoQ/AAAAAAAAAAI/AAAAAAAAAFY/TrDxSDdQuhQ/s512-c/photo.jpg";   
  21.         //String sFileURL = "http://xinsheng-image.huawei.com/cn/forumimage/showimage-816607-f61c8fe14fc359d49b044376a0956acd-self.jpg";   
  22.         //String sFileURL = "http://3.bp.blogspot.com/-oVO24VW8F6M/TxJ9O0opP3I/AAAAAAAAANY/anpu8S4FAC4/s640/100_9223.JPG";   
  23.         String sFileURL = "http://hi.csdn.net/attachment/201201/1/0_1325433530Bg5e.gif";  
  24.         sFileURL = "http://west263.newhua.com:82/down/jia-audio-converter.zip";  
  25.         //file save as name   
  26.         String sFileName = sFileURL.substring(sFileURL.lastIndexOf("/") + 1);  
  27.          
  28.         // create a object of download tool   
  29.         HttpDownloadTool oHttpDownloadTool = new HttpDownloadTool();  
  30.         // download the file   
  31.         oHttpDownloadTool.download(sFileURL, 3, sFileName);  
  32.     }  
  33. }  
package com.ross.httpdownload;
import com.ross.httpdownload.util.*;
/**
 * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
 * Date: 2012-1-19
 * Since: MyJavaExpert v1.0
 * Description: Test the download tool class
 */
public class MyMain
{
    public static void main(String[] args)
    {
        // set system configuration, in real software, it can be configured
        // through GUI, file,etc.
        SysValue.MAX_Num_Of_Thread = 3;
        SysValue.Save_As_Path = "E:/myspace/download/";
        SysValue.Buffer_Size = 1024;
        //file web address
        //String sFileURL = "http://xinsheng-image.huawei.com/cn/forumimage/showimage-991441-20990f56c5b11261fa63e969d8d5580c-self.jpg";
        //String sFileURL = "http://lh5.googleusercontent.com/-F7a0loCDyoQ/AAAAAAAAAAI/AAAAAAAAAFY/TrDxSDdQuhQ/s512-c/photo.jpg";
        //String sFileURL = "http://xinsheng-image.huawei.com/cn/forumimage/showimage-816607-f61c8fe14fc359d49b044376a0956acd-self.jpg";
        //String sFileURL = "http://3.bp.blogspot.com/-oVO24VW8F6M/TxJ9O0opP3I/AAAAAAAAANY/anpu8S4FAC4/s640/100_9223.JPG";
        String sFileURL = "http://hi.csdn.net/attachment/201201/1/0_1325433530Bg5e.gif";
        sFileURL = "http://west263.newhua.com:82/down/jia-audio-converter.zip";
        //file save as name
        String sFileName = sFileURL.substring(sFileURL.lastIndexOf("/") + 1);
       
        // create a object of download tool
        HttpDownloadTool oHttpDownloadTool = new HttpDownloadTool();
        // download the file
        oHttpDownloadTool.download(sFileURL, 3, sFileName);
    }
}

a. 可以多线程下载的zip文件测试

URL: http://west263.newhua.com:82/down/jia-audio-converter.zip

线程数: 3

控制台打印信息:

  1. the file is stored as "E:/myspace/download/jia-audio-converter.zip".  
  2. the file length is 5720120.  
  3. The download thread 1 is started at 2012-01-21 00:49:23  
  4. The download index of 1 is 1906706 to 3813411  
  5. The download thread 0 is started at 2012-01-21 00:49:23  
  6. The download index of 0 is 0 to 1906705  
  7. The download thread 2 is started at 2012-01-21 00:49:23  
  8. The download index of 2 is 3813412 to 5720119  
  9. Thread 0 download is finished, totaly: 1906706  
  10. The download thread 0 is ended at 2012-01-21 00:58:09  
  11. Thread 1 download is finished, totaly: 1906706  
  12. The download thread 1 is ended at 2012-01-21 01:06:17  
  13. Thread 2 download is finished, totaly: 1906708  
  14. The download thread 2 is ended at 2012-01-21 01:07:05  
the file is stored as "E:/myspace/download/jia-audio-converter.zip".
the file length is 5720120.
The download thread 1 is started at 2012-01-21 00:49:23
The download index of 1 is 1906706 to 3813411
The download thread 0 is started at 2012-01-21 00:49:23
The download index of 0 is 0 to 1906705
The download thread 2 is started at 2012-01-21 00:49:23
The download index of 2 is 3813412 to 5720119
Thread 0 download is finished, totaly: 1906706
The download thread 0 is ended at 2012-01-21 00:58:09
Thread 1 download is finished, totaly: 1906706
The download thread 1 is ended at 2012-01-21 01:06:17
Thread 2 download is finished, totaly: 1906708
The download thread 2 is ended at 2012-01-21 01:07:05
下载的文件抓图:


b.可以多线程下载的图片测试

URL: http://hi.csdn.net/attachment/201201/1/0_1325433530Bg5e.gif

线程数: 3

控制台打印信息:

  1. the file is stored as "E:/myspace/download/0_1325433530Bg5e.gif".  
  2. the file length is 23304.  
  3. The download thread 2 is started at 2012-01-21 02:03:00  
  4. The download thread 0 is started at 2012-01-21 02:03:00  
  5. The download index of 2 is 15536 to 23303  
  6. The download index of 0 is 0 to 7767  
  7. The download thread 1 is started at 2012-01-21 02:03:00  
  8. The download index of 1 is 7768 to 15535  
  9. Thread 2 download is finished, totaly: 7768  
  10. The download thread 2 is ended at 2012-01-21 02:03:01  
  11. Thread 1 download is finished, totaly: 7768  
  12. The download thread 1 is ended at 2012-01-21 02:03:01  
  13. Thread 0 download is finished, totaly: 7768  
  14. The download thread 0 is ended at 2012-01-21 02:03:02  
the file is stored as "E:/myspace/download/0_1325433530Bg5e.gif".
the file length is 23304.
The download thread 2 is started at 2012-01-21 02:03:00
The download thread 0 is started at 2012-01-21 02:03:00
The download index of 2 is 15536 to 23303
The download index of 0 is 0 to 7767
The download thread 1 is started at 2012-01-21 02:03:00
The download index of 1 is 7768 to 15535
Thread 2 download is finished, totaly: 7768
The download thread 2 is ended at 2012-01-21 02:03:01
Thread 1 download is finished, totaly: 7768
The download thread 1 is ended at 2012-01-21 02:03:01
Thread 0 download is finished, totaly: 7768
The download thread 0 is ended at 2012-01-21 02:03:02
下载的文件抓图:


c. 不能多线程下载图片

URL: http://3.bp.blogspot.com/-oVO24VW8F6M/TxJ9O0opP3I/AAAAAAAAANY/anpu8S4FAC4/s640/100_9223.JPG

线程数: 3

控制台打印信息:

  1. This site do not support multiple thread download, reset the thread to 1  
  2. the file is stored as "E:/myspace/download/100_9223.JPG".  
  3. the file length is 170398.  
  4. The download thread 0 is started at 2012-01-21 02:06:54  
  5. The download index of 0 is 0 to 170397  
  6. Thread 0 download is finished, totaly: 170398  
  7. The download thread 0 is ended at 2012-01-21 02:06:55  
This site do not support multiple thread download, reset the thread to 1
the file is stored as "E:/myspace/download/100_9223.JPG".
the file length is 170398.
The download thread 0 is started at 2012-01-21 02:06:54
The download index of 0 is 0 to 170397
Thread 0 download is finished, totaly: 170398
The download thread 0 is ended at 2012-01-21 02:06:55
下载的文件抓图:

到这里整个demo完成了.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值