用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批量下載/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM