Spring 4.3.2下實現http多次斷點下載


其實跟 spring 無關,如果是直接下載資源很多 web sever 不用程序就直接實現了斷點。

但我們的應用是 download?url=xxxx 這種方式 下載資源由 download 來負責,所以得手工改寫一下代碼。

斷點續傳,聽上去似乎是個比較高級的話題,我們現在用的是http版的斷點續傳,其他協議的大家可以自行研究。

http協議中,服務端實現斷點續傳首先需要讀取客戶端傳送的Range頭信息,比如“Range: bytes=12583394-這個就是指原來正在下載的文件需要從第12583394字節繼續下載,然后我們利用java.io.File的skip方法,舍棄掉原文件的前n個字節,接着就繼續慢慢write吧。。。

但是客戶端又是如何判斷服務端是否支持斷點續傳的呢?主要就是Accept-Ranges和Content-Length頭信息。比如“Accept-Ranges:bytes”和“Content-Length:99999999”。有了這兩個頭信息,客戶端就認為服務端是支持斷點續傳的了。

然后需要注意的是,假如客戶端剛才由於某些原因,暫停了下載,現在恢復的時候,就會如前所述,傳來Range頭信息,這時候,我們的response就需要設置一下狀態碼,這里應該設置成206(詳細解釋請看http://en.wikipedia.org/wiki/List_of_HTTP_status_codes),還有就是Content-Range頭信息,格式為“bytes x-(y-1)/y”,x就是客戶端傳來的開始字節位置,y就是文件長度。

理解了這些,再看看給出的實例關鍵代碼:

 

 1                     response.reset();
 2                     response.setCharacterEncoding("utf-8");
 3                     response.setContentType("application/x-download");
 4                     response.setHeader("Accept-Ranges", "bytes");
 5                     response.setHeader("Content-Length", String.valueOf(fSize));
 6                     response.setHeader("Content-Disposition", "attachment; filename=\"" + new String(filename.getBytes(guessCharset), "iso-8859-1") + "\"");
 7                     in = new FileInputStream(file.getPath());
 8 
 9                     long pos = 0;
10                     if (null != request.getHeader("Range")) {
11                         // 斷點續傳
12                         response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
13                         try {
14                             pos = Long.parseLong(request.getHeader("Range").replaceAll("bytes=", "").replaceAll("-", ""));
15                         } catch (NumberFormatException e) {
16                             pos = 0;
17                         }
18                     }
19                     out = response.getOutputStream();
20                     String contentRange = new StringBuffer("bytes ").append(pos + "").append("-").append((fSize - 1) + "").append("/").append(fSize + "").toString();
21                     response.setHeader("Content-Range", contentRange);
22                     in.skip(pos);
23                     byte[] buffer = new byte[1024 * 10];
24                     int length = 0;
25                     while ((length = in.read(buffer, 0, buffer.length)) != -1) {
26                         out.write(buffer, 0, length);
27                         // Thread.sleep(100);
28                     }

再來看一下效果圖:


免責聲明!

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



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