• 用java实现文件的断点续传并发下载


    需求:

    支持文件批量下载。现在有很多小图片需要批量下载,不希望在服务器打包下载。

    支持大文件断点下载。比如下载10G的文件。

    PC端全平台支持。Windows,macOS,Linux

    全浏览器支持。ie6,ie7,ie8,ie9,ie10,ie11,edge,firefox,chrome,safari

    支持文件夹结构下载。不希望在服务器打包,而是直接下载文件夹,下载后在本地文件夹结构和服务器保持一致。

    支持从URL中下载文件。

    支持JSON数据结构。

     

    说明

    用java实现文件的断点续传,使用了HTTP的首部字段实现,在网上看到例子,手动实现一遍,理解其原理,在这记录下

     

    正文

    要实现断点续传,要在请求中设置请求开始的位置和结束位置,在HTTP请求中设置RANGE首部字段,之后服务器如果能正常返回,返回206状态码

    用java实现的关键点:

    1.设置请求的首部字段,使用java的net包

    2.在读取资源文件后,要保存文件,从断点处保存,使用RandAccessFile类

    3.使用多线程并发的方式进行,如何正确设置起始位置

     

    主要思路就是:

    1. 设置文件信息,包括文件所在的URL,文件名,文件保存的路径及文件需要分段下载的次数

    2. 下载时,先连接服务器,得到文件的大小,通过服务器响应的首部字段Content-Length获得,得到文件大小后,根据分段下载的次数设置每次开始的位置,结束位置。并创造一个信息临时文件,用来保存每次分段下载的起始位置,用于非第一次下载时,可以直接本地读取起始信息

    3. 分段下载根据开始位置,保存在下载文件的合适位置,使用RandAccessFile类的seek()方法定位

     

    文件分块下载代码

    <%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>

    <%@page contentType="text/html;charset=UTF-8"%>

    <%@page import="down2.*" %>

    <%@page import="java.net.URLDecoder" %>

    <%@page import="java.net.URLEncoder" %>

    <%@page import="org.apache.commons.lang.*" %>

    <%@page import="com.google.gson.FieldNamingPolicy" %>

    <%@page import="com.google.gson.Gson" %>

    <%@page import="com.google.gson.GsonBuilder" %>

    <%@page import="com.google.gson.annotations.SerializedName" %>

    <%@page import="java.io.*" %>

    <% out.clear();

    /*

        下载数据库中的文件。

        更新记录:

            2015-05-13 创建

            2017-12-09 完善Range协议

    */

    String fileName = "网易云音乐.exe";//客户端保存的文件名

    String filePath = "d:\文件校验工具.exe";//路径

     

    fileName = URLEncoder.encode(fileName,"UTF-8");

    fileName = fileName.replaceAll("\+","%20");

    response.setContentType("application/octet-stream;charset:utf-8");

    response.addHeader("Content-Disposition","attachment;filename=" + fileName);

    response.addHeader("Pragma""No-cache");

    response.addHeader("Cache-Control""No-cache");

    response.addHeader("Expires""0");

     

    //定位文件块索引

    File f = new File(filePath);

    long fileLen = f.length();

    long blockSize = fileLen;//块大小

    long blockBegin = 0;

    long blockEnd = 0;

    RandomAccessFile raf = new RandomAccessFile(filePath,"r");

    FileInputStream in = new FileInputStream( raf.getFD() );

    String range = request.getHeader("Range");

    if(range != null)

    {

        //清除bytes=

        int pos = range.indexOf("=");

        if(pos != -1) range = range.substring(pos+1);

       

        /*

            1-

            -1

            0-1

        */

        String[] rs = range.split("-");//bytes=10254

        //-1

        if( StringUtils.isEmpty(rs[0]) )

        {

            blockSize = Long.parseLong(rs[1]);

            in.skip(fileLen - blockSize);

            blockEnd = fileLen - 1;

            blockBegin = fileLen - blockSize;

        }//1-

        elseif( StringUtils.isEmpty(rs[1]))

        {

            blockBegin = Long.parseLong(rs[0]);

            in.skip(blockBegin);

            blockSize = fileLen - blockBegin;

            blockEnd = (blockBegin + blockSize) - 1;

        }//1-1

        else

        {

            blockBegin = Long.parseLong(rs[0]);

            blockEnd = Long.parseLong(rs[1]);

            blockSize = (blockEnd - blockBegin) + 1;

            in.skip(blockBegin);

        }

    }

    response.addHeader("Content-Length",Long.toString(blockSize));

    response.addHeader("Content-Range",String.format("bytes %d-%d/%d",blockBegin,blockEnd,fileLen) );

     

    byte[] b = newbyte[1048576];//一次读1MB数据,如果服务器内存足够,可适当调大尺寸。

    int i = 0;

     

    OutputStream outp = response.getOutputStream();

    while((i = in.read(b)) > 0)

    {

        outp.write(b, 0, i);

    }

    outp.flush();

     

    in.close();

    outp.close();

    in  = null;

    outp = null;

    %>

     

    2、文件的保存

    文件保存由前端实现。由用户下载前选择文件的下载路径。

     

    3、批量下载

    批量下载通过urls参数即可实现。

    $("#btn-down-files").click(function (){

        if(downer.Config["Folder"]==""){ downer.open_folder();return;}

        var urls =[

            { fileUrl:"http://res2.ncmem.com/res/images/ie11.png"}

            ,{ fileUrl:"http://res2.ncmem.com/res/images/up6.1/down.png"}

            ,{ fileUrl:"http://res2.ncmem.com/res/images/firefox.png"}

            ,{ fileUrl:"http://res2.ncmem.com/res/images/edge.png"}

            ,{ fileUrl:"http://res2.ncmem.com/res/images/up6.1/cloud.png"}

            ,{ fileUrl:"http://res2.ncmem.com/res/images/home/w.png"}

            ,{ fileUrl:"http://res2.ncmem.com/res/images/img.png"}

        ];

        downer.app.addUrls(urls);

    });

     

    4、自定义下载文件夹名称

    基本信息包含了文件所在站点信息,文件本地保存路径,文件名,文件分段下载次数

    $("#btn-down-json").click(function (){

        if(downer.Config["Folder"]==""){ downer.open_folder();return;}

        var fd ={

            nameLoc:"图片列表"

            , files:[

                { fileUrl:"http://res2.ncmem.com/res/images/ie11.png"}

                ,{ fileUrl:"http://res2.ncmem.com/res/images/up6.1/down.png"}

                ,{ fileUrl:"http://res2.ncmem.com/res/images/firefox.png"}

                ,{ fileUrl:"http://res2.ncmem.com/res/images/edge.png"}

                ,{ fileUrl:"http://res2.ncmem.com/res/images/up6.1/cloud.png"}

                ,{ fileUrl:"http://res2.ncmem.com/res/images/home/w.png"}

                ,{ fileUrl:"http://res2.ncmem.com/res/images/img.png"}

            ]

        };

        downer.app.addJson(fd);

    });

     

    5、下载多级目录

    //下载多级目录

    $("#btn-down-fd").click(function (){

        if(downer.Config["Folder"]==""){ downer.open_folder();return;}

        var fd ={

            nameLoc:"测试文件夹"

            , files:[

                { fileUrl:"http://www.ncmem.com/images/ico-ftp.jpg"}

                ,{ fileUrl:"http://www.ncmem.com/images/ico-up.jpg"}

            ]

            , folders:[

                {

                    nameLoc:"图片1"

                    , files:[

                        { fileUrl:"http://www.ncmem.com/images/ico-ftp.jpg"}

                        ,{ fileUrl:"http://www.ncmem.com/images/ico-up.jpg"}

                        ,{ fileUrl:"http://www.ncmem.com/images/ico-capture.jpg"}

                        ,{ fileUrl:"http://www.ncmem.com/images/ico-imageuploader.gif"}

                        ,{ fileUrl:"http://www.ncmem.com/images/ico-wordpaster.gif"}

                    ]

                    , folders:[

                        {

                            nameLoc:"软件"

                            , files:[

                                { fileUrl:"http://res2.ncmem.com/res/images/edit-file.png"}

                            ]

                        }

                    ]

                }

            ]

        };

        downer.app.addJson(fd);

    });

     

    网上例子:http://blog.ncmem.com/wordpress/2019/08/28/java批量下载/

  • 相关阅读:
    使用snmp+mrtg监控CPU、流量、磁盘空间、内存
    ISO20000
    nginx入门篇----nginx服务器基础配置
    oracle数据库备份和还原
    oracle创建删除用户和表空间
    Centos 6.5安装oracle 11g
    nginx入门篇----安装、部署、升级
    vue 高德地图 地图初始化显示接口返回的多个经纬度
    vue element UI el-table 单元格中超出字省略号显示
    vue + element ui 打印
  • 原文地址:https://www.cnblogs.com/songsu/p/11542236.html
Copyright © 2020-2023  润新知