2010-07-21 68 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