多线程下载断点续传

来源:互联网 发布:php面向对象的封装 编辑:程序博客网 时间:2024/06/07 17:23

多线程下载断点续传

这里写图片描述

多线程下载断点续传

1.了解一下多线程下载的思路

    思路:开启多个线程下载同一个文件,这样可以使我们的下载文件的速度加快。如果我们使用单一的线程去下载。下载速度慢。

断点续传

1.断点续传需要在下载过程中记录每条线程的下载进度2.每次下载开始之前先读取数据库,查询是否有未完成的记录,有就继续下载,没有则创建新记录插入数据库3.在每次向文件中写入数据之后,在数据库中更新下载进度4.下载完成之后删除数据库中下载记录

多线程下载的步骤

(1)首先获得下载文件的长度,然后设置本地文件的长度。
HttpURLConnection.getContentLength();//获取下载文件的长度
RandomAccessFile file = new RandomAccessFile(“QQWubiSetup.exe”,”rwd”);
file.setLength(filesize);//设置本地文件的长度
(2)根据文件长度和线程数计算每条线程下载的数据长度和下载位置。
如:文件的长度为6M,线程数为3,那么,每条线程下载的数据长度为2M,每条线程开始下载的位置如
例如10M大小,使用3个线程来下载,
线程下载的数据长度 (10%3 == 0 ? 10/3:10/3+1) ,第1,2个线程下载长度是4M,第三个线程下载长度为2M
下载开始位置:线程id*每条线程下载的数据长度 = ?
下载结束位置:(线程id+1)*每条线程下载的数据长度-1=?
(3)使用Http的Range头字段指定每条线程从文件的什么位置开始下载,下载到什么位置为止,
如:指定从文件的2M位置开始下载,下载到位置(4M-1byte)为止
代码如下:HttpURLConnection.setRequestProperty(“Range”, “bytes=2097152-4194303”);
(4)保存文件,使用RandomAccessFile类指定每条线程从本地文件的什么位置开始写入数据。
RandomAccessFile threadfile = new RandomAccessFile(“QQWubiSetup.exe “,”rwd”);
threadfile.seek(2097152);//从文件的什么位置开始写入数据

多线程下载断点续传的源码:

/**     * 开启线程的数量     */    static int threadCount=3;    /**     * 访问下载的路径     */    static String path="http://169.254.87.122:8080/baofeng.exe";    static int threadFinished=0;    public static void main(String[] args) {        try {            //创建URL对象  参数:设置路径            URL url=new URL(path);            //打开连接,通过强制类型转换HttpURLConnection            HttpURLConnection connection=(HttpURLConnection) url.openConnection();            //设置请求的方式            connection.setRequestMethod("GET");            //设置读取的时间            connection.setReadTimeout(5000);            //设置连接的时间            connection.setConnectTimeout(5000);            if (connection.getResponseCode()==200) {                //拿到要下载文件的大小                int length = connection.getContentLength();                //指定临时文件的路径和文件名                File file=new File(getFileName(path));                //创建随机存储文件对象                RandomAccessFile raf=new RandomAccessFile(file, "rwd");                //设置临时文件的大小和服务器的一模一样                raf.setLength(length);                //计算每个线程下载的字节数                int size=length/threadCount;                for (int i = 0; i <threadCount; i++) {                    //计算3个线程的开始位置和结束位置                    int startIndex=i*size;                    int endIndex=(i+1)*size-1;                    //如果是最后一个线程,那么结束位置特殊处理                    if (i==threadCount-1) {                        endIndex=length-1;                    }                    System.out.println("线程"+i+"-----------"+startIndex+"-------"+endIndex);                    DowndLoadThread thread = new DowndLoadThread(i, startIndex, endIndex);                    thread.start();                }            }        } catch (Exception e) {            e.printStackTrace();        }    }    /**     * 得到文件名字的     * @param path 传入的访问的路径     * @return 返回处理后的结果     */    public  static String getFileName(String path){        //找到最后/的索引        int index = path.lastIndexOf("/");        //进行截取        return path.substring(index+1);    }     static class DowndLoadThread extends Thread{        int threadId;        int startIndex;        int endIndex;        /**         * 创建有参构造函数         * @param threadId 第几个线程的         * @param startIndex 开始的索引         * @param endIndex   结束的索引         */        public DowndLoadThread( int threadId,int startIndex, int endIndex) {            super();            this.startIndex = startIndex;            this.endIndex = endIndex;            this.threadId = threadId;        }        @Override        public void run() {            super.run();            URL url;            try {                //设置线程从那个位置开始写入数据到临时文件                File fileProgress=new File("h://"+threadId+".txt");                //判断下载的临时文件是否存在                if (fileProgress.exists()) {                    FileInputStream fis=new FileInputStream(fileProgress);                    BufferedReader br=new BufferedReader(new InputStreamReader(fis));                    //拿到临时文件所存储的位置                    int newStartIndex = Integer.parseInt(br.readLine());                    startIndex=newStartIndex;                    System.out.println("线程"+threadId+"最终位置---------------"+startIndex);                }                url = new URL(path);                HttpURLConnection connection=(HttpURLConnection) url.openConnection();                connection.setRequestMethod("GET");                connection.setReadTimeout(5000);                connection.setConnectTimeout(5000);                //设置请求数据的范围                connection.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);                if (connection.getResponseCode()==206) {                    InputStream is = connection.getInputStream();                    int len=0;                    byte[] b=new byte[1024];                    int total=0;                    File file=new File("h://"+MuiltDownLoad.getFileName(path));                    //创建随机文件的存储对象                    RandomAccessFile raf=new RandomAccessFile(file, "rwd");                    raf.seek(startIndex);                    //记录当前下载进度                    int currentPosition=startIndex;                    while((len=is.read(b))!=-1){                        //把下载下来的临时文件写入raf临时文件                        raf.write(b, 0, len);                        total+=len;                        @SuppressWarnings("resource")                        RandomAccessFile rafProgress=new RandomAccessFile(fileProgress, "rwd");                        currentPosition=startIndex+total;                        //把下载进度写入rafProgress临时文件,下一次下载时作为新的startIndex                        rafProgress.write((currentPosition+"").getBytes());                        System.out.println("线程"+threadId+"---------------"+total);                    }                    raf.close();                    System.out.println("线程"+threadId+"下载完毕");                    MuiltDownLoad.threadFinished++;                    //如果这个条件成立,说明线程下载完毕                    synchronized (MuiltDownLoad.path) {                        if (MuiltDownLoad.threadFinished==MuiltDownLoad.threadCount) {                            for (int i = 0; i < MuiltDownLoad.threadCount; i++) {                                File temp=new File("h://"+i+".txt");                                temp.delete();                            }                            MuiltDownLoad.threadFinished=0;                        }                    }                }            } catch (Exception e) {                e.printStackTrace();            }        }    }
0 0
原创粉丝点击