多线程下载文件,以及断点下载

一:前言

多线程下载文件,可能有的同学没有过多的听说过,但是断点下载肯定是听过的,也就是说像讯雷,哪怕你把电脑重启了,讯雷重新启动后也会接着原来的地方下载,那么这是怎么做到的呢?

二:代码示例

直接给出代码,

2.1、经典代码

两行经典的代码分别为:

//设置下载的开始及结束位置
conn.setRequestProperty("Range", "bytes="+start+"-"+end+"");
//设置读写的起点位置
RandomAccessFile raf = new RandomAccessFile("e:/test/temp.exe","rw");
raf.seek(start);

2.2、完整代码:

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;

public class Demo {
    /**
     * 下载线程数量<br>
     * 我用5个线程下载用了37秒,用1个线程下载用了45秒
     */
    private static int num = 5;

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

    public final static void threadDown() {
        try {
            URL url = new URL("http://dldir1.qq.com/qqfile/qq/QQ8.2/17724/QQ8.2.exe");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            int size = conn.getContentLength();
            // 每个纯种下载该大小
            int block = size / num;

            // 这个类支持对于文件的随机访问,第一个参数是文件名,第二个是访问模式,rw代表读写
            RandomAccessFile raf = new RandomAccessFile("e:/test/temp.exe","rw");
            // 在本地创建一个空文件,大小与服务器的文件保持一致
            raf.setLength(size);
            raf.close();

            // 定义一个开始下载的位置,结束下载的位置
            int start;
            int end;
            for (int i = 0; i < num; i++) {
                start = i * block;
                if (num == i + 1) {
                    end = size;
                } else {
                    end = block * (i + 1);
                }
                System.out.println("开始:" + start + ", 结束:" + end);
                ThreadDown down = new ThreadDown(start,end);
                down.start();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
class ThreadDown extends Thread{
    private int start;
    private int end;
    public ThreadDown(int start,int end){
        this.start = start;
        this.end = end;
    }
    public void run() {
        long startTime = new Date().getTime();
        String name = Thread.currentThread().getName();
        try {
            System.out.println(name + ":启动");
            URL url = new URL("http://dldir1.qq.com/qqfile/qq/QQ8.2/17724/QQ8.2.exe");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //这里也是重点,设置了请求的开始字节与结束字节
            conn.setRequestProperty("Range", "bytes="+start+"-"+end+"");
            InputStream in = conn.getInputStream();
            
            RandomAccessFile raf = new RandomAccessFile("e:/test/temp.exe","rw");
            //设置读写的起点位置,这里是重点
            raf.seek(start);
            byte[] buf = new byte[1024];
            int len = 0;
            while((len=in.read(buf))!= -1){
                raf.write(buf, 0, len);
            }
            
            in.close();
            raf.close();
            long endTime = new Date().getTime();
            long useTime = (endTime - startTime) / 1000;
            System.out.println(name + "下载完成,共耗时:" + useTime + "秒");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    
}

三:断点下载

想来看过了上面的代码,断点下载的原理大家肯定也是知道了,同样的也是采用

//设置下载的开始及结束位置
conn.setRequestProperty("Range", "bytes="+start+"-"+end+"");
//设置读写的起点位置
RandomAccessFile raf = new RandomAccessFile("e:/test/temp.exe","rw");
raf.seek(start);

 

原文地址:https://www.cnblogs.com/zhuxiaojie/p/5384970.html