如何用多线程下载文件

之前的项目中用到多线程下载文件,当然,说具体点我那是多个线程下载多个文件。实际上具体到某一文件时候还只是用了一个线程去下载,这种方式个人认为还是比较适合那中文件小而多的情况。 但这次不同了,项目中要下载并上传的文件进本都在30M以上。这样的话用以前的方式可就OUT了,于是就要使用一个文件多个线程下载的方式了。

同样的还是从代码入手:
import java . io . File ;
import java . io . UnsupportedEncodingException ;
import java . net . HttpURLConnection ;
import java . net . URL ;

public class Main {
    public static int SINGAL = 0;
    public static boolean START_DOWNLOAD = false;
    private int threadNumber; 每个文件下载的线程数
    private String fileName; 文件名
    private String downLoadPath; 文件路径
    private URL url ;
    
    public Main( URL url ) {
        super ( ) ;
        this . url = url ;
        this . threadNumber = 5;
        this . downLoadPath = "c:/download/" ;
        try {
            this . fileName = java . net . URLDecoder . decode ( url . getFile ( ) . substring ( url . getFile ( ) . lastIndexOf ( "/" ) + 1, url . getFile ( ) . length ( ) ) , "GBK" ) ;  //对Url进行转码操作
        } catch ( UnsupportedEncodingException e) {
            e. printStackTrace ( ) ;
        }
    }

    public Main( int threadNumber, String fileName, String downLoadPath, URL url ) {
        super ( ) ;
        this . threadNumber = threadNumber;
        this . fileName = fileName;
        this . downLoadPath = downLoadPath;
        this . url = url ;
    }

    public void download( ) throws Exception {
        System . out. println ( "文件开始下载" ) ;
        START_DOWNLOAD = true;
        HttpURLConnection httpURLConnection = ( HttpURLConnection ) url . openConnection ( ) ;
        int contentLength = httpURLConnection . getContentLength ( ) ;
        
        int partLength = contentLength / threadNumber + 1; //得到该文件的大小
        for ( int i= 0; i< threadNumber; i+ + ) { //根据自己的需要进行文件分块。
            int length = partLength;
            if ( i = = threadNumber - 1) {
                length = contentLength - i * partLength;
            }
            DownloadThread dt = new DownloadThread( url , length , i * partLength, downLoadPath + fileName + ".part" + i) ;
            dt. start ( ) ;
        }
    }

    public int getThreadNumber( ) {
        return threadNumber;
    }

    public void setThreadNumber( int threadNumber) {
        this . threadNumber = threadNumber;
    }

    public String getDownLoadPath( ) {
        return downLoadPath;
    }

    public void setDownLoadPath( String downLoadPath) {
        this . downLoadPath = downLoadPath;
    }

    public String getFileName ( ) {
        return fileName;
    }

    public void setFileName ( String fileName) {
        this . fileName = fileName;
    }

    public URL getUrl ( ) {
        return url ;
    }

    public void setUrl ( URL url ) {
        this . url = url ;
    }

    public static void main( String [ ] args) throws Exception {
        String urlAddress = "http://www.cssxblog.net/qin/mp3/aqzy.mp3" ;

        URL url = new URL ( urlAddress) ;
        int threadNumber = 5;
        String fileName = "test.mp3" ;
        String downLoadPath = "c:/download/" ;
        new File ( downLoadPath) . mkdir ( ) ;
        //下载

        Main m = new Main( url ) ;
        m. setThreadNumber( threadNumber) ;
        m. download( ) ;
        
        //合并文件

        fileName = m. getFileName ( ) ;
        Thread mergeFile = new MergeFile( threadNumber, downLoadPath, fileName) ;
        mergeFile. start ( ) ;
        
    }
}

 

 

 

import java . io . File ;
import java . io . FileInputStream ;
import java . io . FileOutputStream ;
import java . io . IOException ;
import java . io . InputStream ;
import java . io . OutputStream ;

public class MergeFile extends Thread {

    private int threadNumber;
    private String fileName;
    private String downLoadPath;
    
    public MergeFile( int threadNumber, String downLoadPath, String fileName) {
        super ( ) ;
        this . threadNumber = threadNumber;
        this . downLoadPath = downLoadPath;
        this . fileName = fileName;
    }

    public void run ( ) {
        while ( ! ( Main. SINGAL = = 0 & & Main. START_DOWNLOAD) ) {
            try {
                Thread . sleep ( 5000) ;
            } catch ( InterruptedException e) {
                // TODO Auto-generated catch block

                e. printStackTrace ( ) ;
            }
        }
        try {
            System . out. println ( "文件开始合并" ) ;
            OutputStream bos = new FileOutputStream ( new File ( downLoadPath + fileName) , false) ;
            for ( int i = 0; i< threadNumber; i+ + )
            {
                File file = new File ( downLoadPath + fileName + ".part" + i) ;
                InputStream is = new FileInputStream ( file ) ;
                byte [ ] buffer = new byte [ 1024] ;
                int bytesRead;
                while ( ( bytesRead = is. read ( buffer ) ) ! = - 1) {
                    bos. write ( buffer , 0, bytesRead) ;
                }
                is. close ( ) ;
                file . delete ( ) ;
            }
            bos. close ( ) ;
            System . out. println ( "文件合并完成" ) ;
        } catch ( IOException e) {
            // TODO Auto-generated catch block

            e. printStackTrace ( ) ;
        }
        Main. START_DOWNLOAD = false;
    }

    public int getThreadNumber( ) {
        return threadNumber;
    }

    public void setThreadNumber( int threadNumber) {
        this . threadNumber = threadNumber;
    }

    public String getFileName ( ) {
        return fileName;
    }

    public void setFileName ( String fileName) {
        this . fileName = fileName;
    }

    public String getDownLoadPath( ) {
        return downLoadPath;
    }

    public void setDownLoadPath( String downLoadPath) {
        this . downLoadPath = downLoadPath;
    }

}

 

 

 

import java . io . File ;
import java . io . FileOutputStream ;
import java . io . IOException ;
import java . io . InputStream ;
import java . io . OutputStream ;
import java . net . HttpURLConnection ;
import java . net . URL ;

public class DownloadThread extends Thread {
    private URL url ;
    private int length ;
    private int offset;
    private OutputStream bos;
    private String filePath;
    
    public void run ( ) {
        Main. SINGAL+ + ;
        System . out. println ( "线程" + this . getId ( ) + "开始下载" ) ;
        try {
            System . out. println ( "length:" + length ) ;
            System . out. println ( "off:" + offset)
            HttpURLConnection httpConnection = ( HttpURLConnection ) url . openConnection ( ) ;
            httpConnection. setRequestProperty ( "RANGE" , "bytes=" + offset + "-" ) ;

           注意:
           此处一定要设置http请求的属性:这个用于设定请求读取数据的位置。如果不设定有可能数据会损坏。

          InputStream ins = httpConnection. getInputStream ( ) ;
            bos = new FileOutputStream ( new File ( filePath) , false) ;
            byte [ ] buffer = new byte [ 1024] ; //设置缓存的大小
            int bytesRead;
            int size = 0;
            while ( ( bytesRead = ins. read ( buffer ) ) ! = - 1) {
                size + = bytesRead;
                if ( size > length ) {
                    bytesRead = bytesRead - ( size - length ) ;
                }
                bos. write ( buffer , 0, bytesRead) ;
                System . out. println ( "线程" + this . getId ( ) + "下载了" + bytesRead + "字节" ) ;
                if ( size > length ) {
                    break ;
                }
            }
            bos. close ( ) ;
        } catch ( IOException e) {
            // TODO Auto-generated catch block

            e. printStackTrace ( ) ;
        }
        System . out. println ( "线程" + this . getId ( ) + "已经完成" ) ;
        Main. SINGAL- - ;
    }

    public DownloadThread( URL url , int length , int offset, String filePath) {
        super ( ) ;
        this . url = url ;
        this . length = length ;
        this . offset = offset;
        this . filePath = filePath;
    }

    public OutputStream getBos( ) {
        return bos;
    }

    public void setBos( OutputStream bos) {
        this . bos = bos;
    }
}

 

 

以上代码不是自己写的,只是从别人那抄袭而来,此代码没有断点续传,后面准备尝试添加。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值