2010-07-21 67 views
67

我正在閱讀http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 並試圖弄清楚如何繼續文件下載。HTTP範圍標題

例如,假設一個文件的長度爲100個字節,並且我擁有所有的100個字節。不過,我不知道預期的文件大小應該是什麼,所以我要求的文件,並指定一個範圍頭,看起來像這樣:

Range: bytes=100- 

這是一個有效的範圍請求?

+5

Erm,它下面的示例引用'bytes = 9500-'爲有效,因此... – Wrikken 2010-07-21 19:36:39

+1

最新的參考是RFC7233 - http://httpwg.github.io/specs/rfc7233.html – 2015-04-16 21:24:44

+0

您可以首先創建HEAD請求並檢查文件長度。 – 2017-06-16 21:46:53

回答

45

這是一個語法上有效的請求,但不是可滿足的請求。如果您在該節中進一步看你看:

如果語法上有效字節範圍集包括至少一個字節級的範圍,規範其第一個字節,POS小於實體 - 當前長度正文,或至少一個後綴字節範圍規範與非零後綴長度,則字節範圍集是可滿足的。否則,字節範圍集是不可滿足的。 如果字節範圍集合不可滿足,服務器應該返回狀態爲416(請求範圍不可滿足)的響應。否則,服務器應該返回狀態爲206(部分內容)的響應,其中包含實體主體的可滿足範圍。

所以我想在你的例子中,服務器應該返回一個416,因爲它不是該文件的有效字節範圍。

+0

那麼有沒有什麼方法讓客戶端可以在不進行HEAD調用的情況下恢復下載,先找出內容長度,然後再進行數學計算並獲取實際內容?我的意思是某種開放的地址,例如「給我所有字節在這樣和那樣的字節之後......」 – dhruvbird 2010-07-21 20:18:10

+5

客戶端將已經知道它是否具有來自原始請求的所有數據 - 它應該已經接收到內容長度報頭在原始響應中,或者如果它是分塊編碼,它將會收到一個零長度的塊來表示響應已完成。 如果你還沒有保存這個狀態,並且只有磁盤上的一大塊字節,那麼你就必須做一個HEAD請求或使用Range頭來請求一個字節範圍,如果你回來了一個416響應,你知道你有所有的字節。 – 2010-07-21 20:41:30

+0

我認爲Expect-Continue可以讓您按照想要的方式或多或少地進行流式傳輸? – MJB 2011-06-10 03:37:36

115

由於Wrikken建議,這是一個有效的請求。客戶端請求媒體或恢復下載時也很常見。

客戶端通常會測試以查看服務器是否處理遠程請求,而不僅僅是尋找Accept-Ranges響應。 Chrome 總是發送一個Range: bytes=0-與它的第一個GET請求的視頻,所以這是你不能忽視的東西。

每當客戶端在請求中包含Range:時,即使它格式不正確,也期待部分內容(206)響應。當您在HTML5視頻播放期間尋求前進時,瀏覽器僅請求開始點。例如:

Range: bytes=3744- 

因此,爲了讓客戶端正確播放視頻,您的服務器必須能夠處理這些不完整的範圍請求。

您可以處理你在你的問題中指定的「範圍」的類型有兩種:

首先,你可以在響應中給出的要求出發點回覆,然後將文件減一的總長度(請求的字節範圍爲零索引)。例如:

請求:

GET /BigBuckBunny_320x180.mp4 
Range: bytes=100- 

響應:

206 Partial Content 
Content-Type: video/mp4 
Content-Length: 64656927 
Accept-Ranges: bytes 
Content-Range: bytes 100-64656926/64656927 

其次,你可以在請求和開放式的文件長度(大小)給出的起點答覆。這適用於網絡廣播或其他媒體,其總長度未知。例如:

請求:

GET /BigBuckBunny_320x180.mp4 
Range: bytes=100- 

響應:

206 Partial Content 
Content-Type: video/mp4 
Content-Length: 64656927 
Accept-Ranges: bytes 
Content-Range: bytes 100-64656926/* 

提示:

,必須始終包含在範圍內的內容長度作出迴應。如果範圍是完全的,開始到結束,則內容長度簡單地區別:

請求: 範圍:字節= 500-1000

響應: 內容範圍:500-1000字節/ 123456

記住的範圍是0指數的,所以Range: bytes=0-999實際上是要求1000個字節,而不是999,所以用一些模棱兩可的話:

Content-Length: 1000 
Content-Range: bytes 0-999/123456 

或者:

Content-Length: 1000 
Content-Range: bytes 0-999/* 

但是,如果可能的話,應避免使用後一種方法,因爲有些媒體播放器試圖根據文件大小計算持續時間。如果您的請求是針對媒體內容的,這是我的預感,那麼您應該在響應中包含其持續時間。這通過以下格式完成:

X-Content-Duration: 63.23 

這必須是浮點數。不像Content-Length,這個值不一定是準確的。它被用來幫助玩家尋找視頻。如果您正在播放網絡直播,並且只能對其播放時間有一個大致的瞭解,那麼最好包括您的預計播放時間,而不是完全忽略它。因此,對於兩小時的網絡直播,您可以包括像:

X-Content-Duration: 7200.00 

隨着一些媒體類型,如WebM功能,還必須包含內容類型,如:

Content-Type: video/webm 

所有這些都是媒體正常播放所必需的,特別是在HTML5中。如果你沒有給出持續時間,玩家可能會嘗試從其文件大小中找出持續時間(以便尋找),但這不準確。這很好,對於網絡直播或實時流媒體來說是必要的,但對於播放視頻文件並不理想。您可以使用FFMPEG等軟件提取持續時間,並將其保存在數據庫中,甚至可以保存在文件名中。

X-Content-Duration正在被淘汰,以支持Content-Duration,所以我也會包括這一點。一個基本的,響應「0-」請求將至少包括以下內容:

HTTP/1.1 206 Partial Content 
Date: Sun, 08 May 2013 06:37:54 GMT 
Server: Apache/2.0.52 (Red Hat) 
Accept-Ranges: bytes 
Content-Length: 3980 
Content-Range: bytes 0-3979/3980 
Content-Type: video/webm 
X-Content-Duration: 2054.53 
Content-Duration: 2054.53 

還有一點:瀏覽器總是使用它的第一個視頻請求如下:

Range: bytes=0- 

有些服務器會發送一個普通的200響應作爲它接受的響應(但是隻有有限的播放選項),但是嘗試發送206而不是服務器處理範圍。​​表示忽略範圍標題是可以接受的。

+1

誰在致力於Content-Duration的定義?鏈接? – 2013-09-11 15:33:57

+0

如果內容是一個沒有固定持續時間的實時視頻流,你會怎麼做? – 2014-02-16 21:12:15

+0

@Joel,即使你不知道,你也需要回復一段時間。在這種情況下,只需嘗試0.0。對於客戶端來說,持續時間並不重要,因爲您通常無法掃描實時流。如果0.0不起作用,那就試試像1000000.00這樣的非常高的東西。 – 2014-04-02 01:55:57

7

與馬克諾瓦科夫斯基的答案相反,由於某種原因,這個答案已被許多人贊成,是的,這是一個有效且可滿足的要求。事實上,正如Wrikken指出的那樣,標準就是這樣一個例子。在實踐中,Firefox會按照預期響應這些請求(使用206代碼),這正是我用來實現漸進式下載的內容,也就是說,只能獲得實時增長的輪詢日誌文件的尾部。

+2

請再次閱讀Marc Novakowki的回答。 「可以滿足」在他引用的RFC中有特別的含義。此請求不可滿足,因爲請求的字節超出了文件的長度。 – 2015-11-09 04:49:11