JAVA支持HTTP斷點續傳

背景

    這兩天在實現一個基於HTML5在線音視頻播放,因爲文件是存放於企業網盤中的,HTTP不可達,所以須要用程序來實現文件的讀取和HTTP協議的下載。

    用Java實現文件下載也不用多說了,讀取文件,經過二進制流的方式往response裏寫就好了。H5播放器調用也能進行播放了;然而當我控制進度的前進和後退時,問題來了,竟然一點效果都沒有!沒有快進播放器還叫播放器嗎? java

分析

    首先看到播放器沒法取得音視頻文件的時間長度,很天然想到Content-Length屬性,後臺經過file.length()取得文件長度並設置到Content-Length上(代碼以下),前臺播放器裏能夠顯示音視頻的長度了,而且能夠快進了;然而當我快退的時候,仍是無效,同時後臺報錯。
測試

response.addHeader("Content-Length", file.length());



    換了一個HTTP文件進行比較測試,發現直接HTTP訪問的可以正常快進快退。仔細分析二者的request和response頭,發現了區別,請求參數多了以下圖所示屬性,該屬性表名須要從服務端獲取的資源範圍,默認從第一個字節開始取,快進快退實際上就是經過指定這個 Range屬性來肯定你所指望的起始點。

    然而這個屬性是在請求頭上的,客戶端又是怎麼知道要添加這個屬性呢?繼續尋找發現了 Accept-Ranges這個屬性,屬性值是bytes,其代表是否接受獲取其某個實體的一部分(好比文件的一部分)的請求。bytes:表示接受,none:表示不接受。與此對應的response中另一個屬性 Content-Range,其表名該響應包含的部分對象爲整個對象的哪一個部分。完整響應頭以下:


解決

根據上面的分析,咱們就知道在服務端該怎麼處理了,首先在響應頭上添加Accept-Rangesthis

response.setHeader("Accept-Ranges", "bytes");

接着判斷request中是否存在Range屬性,便是否指定的起點,若存在,則經過stream的skip直接跳到目標起點,最後添加Content-Range屬性表名當前塊的起始和結束,完整代碼以下: spa

stream = new FileInputStream(file);
if(request.getHeader("Range") != null) //客戶端請求的下載的文件塊的開始字節   
  {
    //從請求中獲得開始的字節   
    //請求的格式是:   
    //Range: bytes=[文件塊的開始字節]-  
    String range = StringUtils.substringBetween(request.getHeader("Range"), "bytes=", "-");
    long start = Long.parseLong(range);   
    //下載的文件(或塊)長度   
    //響應的格式是:   
    //Content-Length: [文件的總大小] - [客戶端請求的下載的文件塊的開始字節]   
    response.setHeader("Content-Length", String.valueOf(fileSize - start));   
			   
    if (start != 0)  
    {
      //要設置狀態   
      //響應的格式是:   
      //HTTP/1.1 206 Partial Content  
	           response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);//206   
      //不是從最開始下載,   
      //響應的格式是:   
      //Content-Range: bytes [文件塊的開始字節]-[文件的總大小 - 1]/[文件的總大小]   
      response.setHeader("Content-Range","bytes " + start + "-" + String.valueOf(fileSize - 1) + "/" + String.valueOf(fileSize));  
  			   
      stream.skip(start);
      }
    }
    responseBinaryStream(response, this.getContentType(FilenameUtils.getExtension(fileName)), stream);
相關文章
相關標籤/搜索