断点续传(大文件的下载)后台功能实现

某网盘

  • 可以随时暂停、启动
  • 多任务
  • 下载过程中、由于某一些特殊原因(宕机、断电、断网等),导致文件下载失败
    • 再一次下载的时候,还可以继续在原来的基础上下载
    • 当上一次下载的20%,再一次下载的时候,从20%继续下载
  • 本地都会产生一个临时数据文件
    • 中断后,文件不会消失

 

断点续传

 

原理:

实现:

长连接:socket、urlconnection、http、okhttp、httpclient

思路:

  • 指定URL
  • 建立一个目录(指定临时文件)
  • 从服务器中获取对象流
  • 告诉服务器从哪个位置下标,开始发送数据
  • 将对象流对象,写入到临时文件中
  • 根据读取到的对象流长度来进行定义
  • 如果长度有值,则进行写入
  • 如果长度=-1,则无需进行写入操作

代码:

/**
 *
 * @author: likang
 * @date: 2019/12/5 20:44
 * @description: 断点续传(仿百度网盘下载功能)
 */
public class FileDownLoadUtils {

    public static void main(String[] args) {
        //指定URL
        String url = "http://mirrors.aliyun.com/centos/8.0.1905/isos/x86_64/CentOS-8-x86_64-1905-dvd1.iso";
        //下载文件
        downLoadFile(url);
    }

    /*
     * @Description: 创建文件
     * @author: likang
     * @date: 2019/12/5 20:47
     * @params: [url]
     * @return: void
     * @exception:
     */
    private static void downLoadFile(String url) {
        //指定本地下载的目录地址
        File file = new File(FileDownLoadUtils.class.getResource("").getFile());
        //        //生成一个临时文件(目的:主要是记录数据的下标位置(字节长度))
        //        //getAbsolutePath:获取绝对路径
        //        //separator:自动识别当前系统资源分割符合

        file = new File(file.getAbsolutePath() + File.separator + "CentOS-8-x86_64-1905-dvd1.iso.bak");
        //如果目录不存在,则创建
        if(!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //将url中的数据流对象,写入到临时文件中file
        writeFile(url,file);

    }

    /*
     * @Description: 通过url获取服务器对象流,并写入到文件中file
     * @author: likang
     * @date: 2019/12/5 21:00
     * @params: [url, file]
     * @return: void
     * @exception:
     */
    private static void writeFile(String url, File file) {

        byte[] bytes = new byte[1024*1024];
        //定义流对象
        InputStream inputStream = null;//数据流
        FileOutputStream fileOutputStream = null;//写入file对象数据流
        long fileLength = 0;
        int byteCount = 0;
        //根据URL和服务器建立连接---数据流
        try {
            fileOutputStream = new FileOutputStream(file, true);
            fileLength = file.length();
            //建立连接,获取对象流
            inputStream = getInputStream(url,fileLength);
//            byteCount = inputStream.read(bytes);
//            while(byteCount != -1){
//                //数据流---file文件中(临时文件)
//                fileOutputStream.write(bytes, 0, byteCount);
//            }
            while((byteCount = inputStream.read(bytes)) != -1){
                //数据流---file文件中(临时文件)
                fileOutputStream.write(bytes, 0, byteCount);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
             //关闭流对象
            try {
                inputStream.close();
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }



    }

    /*
     * @Description: 建立连接、获取对象流
     * @author: likang
     * @date: 2019/12/5 21:18
     * @params: [url, fileLength]
     * @return: java.io.InputStream
     * @exception:
     */
    private static InputStream getInputStream(String url, long startFileLength) {
        InputStream inputStream = null;
        HttpURLConnection connection;

        try {
            URL filePath = new URL(url);//和服务器建立连接、获取文件路径
            connection = (HttpURLConnection) filePath.openConnection();//开启连接
            connection.setConnectTimeout(3*1000);//连接超时时间
            long lengthLong = connection.getContentLengthLong();//文件的总长度
            if(startFileLength < lengthLong){//还没下载完毕
                connection.disconnect();//销毁链接
                connection = (HttpURLConnection) filePath.openConnection();//开启连接
                connection.setConnectTimeout(3*1000);//连接超时时间
                connection.setRequestProperty("RANGE", "bytes=" + startFileLength + "-");//设置请求发送下标的对象
                System.out.println(connection.getContentLengthLong());
                inputStream = connection.getInputStream();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return inputStream;

    }

}

 

posted @ 2021-07-13 18:06  方大帝的博客  阅读(653)  评论(0编辑  收藏  举报