加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java 文件多线程下载

发布时间:2020-12-15 03:18:30 所属栏目:Java 来源:网络整理
导读:今天PHP站长网 52php.cn把收集自互联网的代码分享给大家,仅供参考。 最近在做文件下载这块的东西,研究了一下多线程文件下载这块的知识。这里只说一下原理,具体实现请看代码,已经写了注释了。 import java.io.File; im

以下代码由PHP站长网 52php.cn收集自互联网

现在PHP站长网小编把它分享给大家,仅供参考

最近在做文件下载这块的东西,研究了一下多线程文件下载这块的知识。这里只说一下原理,具体实现请看代码,已经写了注释了。
import java.io.File;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.RandomAccessFile;  
import java.util.zip.GZIPInputStream;  
  
import org.apache.http.Header;  
import org.apache.http.HttpResponse;  
import org.apache.http.HttpStatus;  
import org.apache.http.client.ClientProtocolException;  
import org.apache.http.client.HttpClient;  
import org.apache.http.client.methods.HttpGet;  
import org.apache.http.client.params.CookiePolicy;  
import org.apache.http.params.CoreConnectionPNames;  
  
import com.ricky.java.common.download.file.http.HttpClientManager;  
import com.ricky.java.common.download.file.util.Constants;  
  
public class Downloader {  
      
    private String url; // 目标地址  
    private File file;  // 本地文件  
    private static final int THREAD_AMOUNT = 3;                 // 线程数  
    private static final String DIR_PATH = "D:/download/file";      // 下载目录  
    private long threadLen;                                     // 每个线程下载多少  
  
    private HttpClient mHttpClient = HttpClientManager.getHttpClient();  
      
    public Downloader(String address) throws IOException {      // 通过构造函数传入下载地址  
        url = address;  
        file = new File(DIR_PATH,address.substring(address.lastIndexOf("?") + 1)+".xml");  
    }  
  
    public void download() throws IOException {  
          
        long totalLen = getContentLength(url);                          // 获取文件长度  
        threadLen = (totalLen + THREAD_AMOUNT - 1) / THREAD_AMOUNT;         // 计算每个线程要下载的长度  
          
        System.out.println("totalLen="+totalLen+"***threadLen="+threadLen);  
          
        RandomAccessFile raf = new RandomAccessFile(file,"rws");           // 在本地创建一个和服务端大小相同的文件  
        raf.setLength(totalLen);                                            // 设置文件的大小  
        raf.close();  
          
        for (int i = 0; i < THREAD_AMOUNT; i++)                              // 开启3条线程,每个线程下载一部分数据到本地文件中  
            new DownloadThread(i).start();  
    }  
      
    public long getContentLength(String address) {  
        HttpGet httpget = null;  
        try {  
            httpget = new HttpGet(address);  
            httpget.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML,like Gecko) Chrome/21.0.1180.79 Safari/537.1");  
            httpget.setHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");  
              
            httpget.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,Constants.SO_TIMEOUT);  
            httpget.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,Constants.CONNECTION_TIMEOUT);  
            httpget.getParams().setParameter("http.protocol.cookie-policy",CookiePolicy.BROWSER_COMPATIBILITY);  
              
            HttpResponse response = mHttpClient.execute(httpget);  
              
            int status = response.getStatusLine().getStatusCode();  
              
            if (status == HttpStatus.SC_OK) {  
                  
                return response.getEntity().getContentLength();  
            }  
        } catch (ClientProtocolException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }finally{  
            if(httpget!=null){  
                httpget.abort();  
            }  
        }  
        return 0;  
    }  
  
    private class DownloadThread extends Thread {  
        private int id;   
        public DownloadThread(int id) {  
            this.id = id;  
        }  
        public void run() {  
            long start = id * threadLen;                        // 起始位置  
            long end = id * threadLen + threadLen - 1;      // 结束位置  
            System.out.println("线程" + id + ": " + start + "-" + end);  
              
            HttpGet httpget = null;  
            try {  
                httpget = new HttpGet(url);  
                httpget.setHeader("User-Agent",like Gecko) Chrome/21.0.1180.79 Safari/537.1");  
                httpget.setHeader("Accept",*/*;q=0.8");  
                  
                httpget.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,Constants.SO_TIMEOUT);  
                httpget.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,Constants.CONNECTION_TIMEOUT);  
                httpget.getParams().setParameter("http.protocol.cookie-policy",CookiePolicy.BROWSER_COMPATIBILITY);  
                  
                HttpResponse response = mHttpClient.execute(httpget);  
                  
                int status = response.getStatusLine().getStatusCode();  
                  
                if (status == HttpStatus.SC_OK) {  
                    InputStream in = response.getEntity().getContent();  
                    Header contentEncoding = response.getFirstHeader("Content-Encoding");  
                    if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {  
                        System.out.println("gzip InputStream in post");  
                        in = new GZIPInputStream(in);  
                    }  
                      
                    RandomAccessFile raf = new RandomAccessFile(file,"rws");  
                    raf.seek(start);  
                      
                    byte[] buffer = new byte[1024];  
                    int len;  
                    while ((len = in.read(buffer)) != -1)  
                        raf.write(buffer,len);  
                    raf.close();  
                      
                    System.out.println("线程" + id + "下载完毕");  
                }else{  
                    System.out.println("线程" + id + "请求失败,响应码="+status);  
                }  
                  
            } catch (ClientProtocolException e) {  
                e.printStackTrace();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }finally{  
                if(httpget!=null){  
                    httpget.abort();  
                }  
            }  
        }  
    }  
      
    public static void main(String[] args) throws IOException {  
//      new Downloader("http://dldir1.qq.com/qqfile/qq/QQ6.2/12179/QQ6.2.exe").download();  
        new Downloader("http://api.t.dianping.com/n/api.xml?cityId=1").download();  
    }  
}  

  
import org.apache.http.client.HttpClient;  
import org.apache.http.conn.scheme.PlainSocketFactory;  
import org.apache.http.conn.scheme.Scheme;  
import org.apache.http.conn.scheme.SchemeRegistry;  
import org.apache.http.conn.ssl.SSLSocketFactory;  
import org.apache.http.impl.client.DefaultHttpClient;  
import org.apache.http.impl.conn.PoolingClientConnectionManager;  
import org.apache.http.params.BasicHttpParams;  
import org.apache.http.params.CoreConnectionPNames;  
import org.apache.http.params.HttpParams;  
  
import com.ricky.java.common.download.file.util.Constants;  
  
public class HttpClientManager {  
      
    private static HttpParams httpParams;  
    private static PoolingClientConnectionManager cm;  
  
    /** 
     * 最大连接数 
     */  
    public final static int MAX_TOTAL_CONNECTIONS = 200;  
    /** 
     * 每个路由最大连接数 
     */  
    public final static int MAX_ROUTE_CONNECTIONS = 300;  
      
  
    static {  
        SchemeRegistry schemeRegistry = new SchemeRegistry();  
        schemeRegistry.register(  
                new Scheme("http",80,PlainSocketFactory.getSocketFactory()));  
        schemeRegistry.register(  
                new Scheme("https",443,SSLSocketFactory.getSocketFactory()));  
          
        cm = new PoolingClientConnectionManager(schemeRegistry);  
        cm.setMaxTotal(MAX_TOTAL_CONNECTIONS);  
        cm.setDefaultMaxPerRoute(MAX_ROUTE_CONNECTIONS);  
          
        HttpParams params = new BasicHttpParams();  
        params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,Constants.CONNECTION_TIMEOUT);  
        params.setParameter(CoreConnectionPNames.SO_TIMEOUT,Constants.SO_TIMEOUT);  
    }  
  
    public static HttpClient getHttpClient() {  
        return new DefaultHttpClient(cm,httpParams);  
    }  
  
}  

如果想实现文件断点下载的话,只需要在记录每个线程当前下载了多少长度的内容即可,可以将其持久化到文件或数据库中保存起来,然后线程开始下载的时候都先读取一下它当前下载了多少就OK了。

以上内容由PHP站长网【52php.cn】收集整理供大家参考研究

如果以上内容对您有帮助,欢迎收藏、点赞、推荐、分享。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读