我正在阅读http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 并试图弄清楚如何继续下载文件。
例如,假设一个文件长度为100个字节,并且我有100个字节。但是,我不知道预期的文件大小应该是什么,所以我要求文件并指定一个如下所示的Range标头:
Range: bytes=100-
这是一个有效的范围请求吗?
答案 0 :(得分:133)
如Wrikken所述,这是一个有效的请求。当客户端请求媒体或恢复下载时,这也很常见。
客户端通常会测试服务器是否处理远程请求,而不仅仅是查找Accept-Ranges
响应。 Chrome 总是向Range: bytes=0-
发送第一个视频的GET请求,因此这是您无法解雇的内容。
每当客户在其请求中包含Range:
时,即使其格式不正确,也会期待部分内容(206)响应。当您在HTML5视频播放期间向前搜索时,浏览器仅请求起始点。例如:
Range: bytes=3744-
因此,为了让客户端正确播放视频,您的服务器必须能够处理这些不完整的范围请求。
您可以通过两种方式处理问题中指定的“范围”类型:
首先,您可以使用响应中给出的请求起始点进行回复,然后文件的总长度减去1(请求的字节范围为零索引)。例如:
请求:
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
请记住,范围是零索引的,因此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
还有一点:Chrome始终使用以下内容启动第一个视频请求:
Range: bytes=0-
某些服务器会发送一个常规的200响应作为回复,它接受(但回放选项有限),但尝试发送206代替显示而不是服务器处理范围。 RFC 2616表示忽略范围标题是可以接受的。
答案 1 :(得分:52)
这是一个语法上有效的请求,但不是一个令人满意的请求。如果您仔细查看该部分,请看:
如果语法上有效的字节范围集包含至少一个byte-range-spec,其first-byte-pos小于entity-body的当前长度,或者至少有一个suffix-byte-range-spec如果后缀长度为非零,则字节范围设置是可以满足的。否则,字节范围设置是不可满足的。 如果字节范围设置不可满足,服务器应该返回状态为416(请求范围不可满足)的响应。否则,服务器应该返回状态为206(部分内容)的响应,其中包含实体主体的可满足范围。
所以我认为在你的例子中,服务器应该返回416,因为它不是该文件的有效字节范围。
答案 2 :(得分:7)
与Mark Novakowski的答案相反,由于某些原因,许多人对此表示赞同,是的,这是一个有效且令人满意的要求。
事实上,正如Wrikken指出的那样,标准就是这样一个例子。在实践中,Firefox会响应预期的这些请求(使用206代码),这正是我用来实现渐进式下载的方式,也就是说,只获得一个长日志文件的尾部,该文件通过轮询实时增长。 / p>
答案 3 :(得分:2)
对于那些在2019年绊倒维克多·斯托达德(Victor Stoddard)的答案并变得充满希望和关注的人们来说,请注意:
a)在Firefox 41中已删除了对X-Content-Duration的支持:https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/41#HTTP
b)我认为Firefox仅支持.ogg音频和.ogv视频,而不支持其他任何类型。
c)我看不到Chrome曾经完全支持它,但这可能只是我缺乏研究。但是,到目前为止,对于Chrome浏览器71中的webm或ogv视频,它的存在与否似乎没有任何影响。
d)我找不到“ Content-Duration”替换为“ X-Content-Duration”的任何地方,我认为“ X-Content-Duration”的生存时间不足以出现后继标头名称。
我认为这意味着,从今天开始,如果您想向Webm或ogv容器提供包含不知道其持续时间(例如ffpeg管道输出)的流的Chrome或FF,并且您希望它们可以在HTML 5视频元素中进行清理,那么您可能不走运。无论您是否通过范围请求进行服务,Firefox 64.0都竭尽全力地使这些可擦写的内容变得可疑,但是如果您查找的次数超出其认为合适的次数,它就会变得混乱并抛出混乱,直到流被完全下载为止。 Chrome甚至不会尝试,它只会停止工作,直到整个流播放完 为止,您才可以彻底擦洗。
答案 4 :(得分:0)
如果您尝试请求长度未知的内容,并且希望它返回连续(或聚合)响应,那么您可能需要考虑使用 RFC8673 中建议的方法 - 即将 last-byte-pos
设置为 2^^53-1,以便您的请求看起来像这样:
GET /resource HTTP/1.1
Host: example.com
Range: bytes=0-9007199254740991