HTTP range 请求允许我们从服务器上只发送HTTP消息的一部分到客户端。这样的部分请求对于大型媒体、具有中断和恢复下载进度的下载文件请求很有帮助。
在进行HTTP range 请求之前,先检查服务器是否支持部分请求
如果请求一个资源时, HTTP响应中出现如下所示的 'Accept-Ranges', 且其值不是none, 那么服务器支持范围请求。
curl -I http://i.imgur.com/z4d4kWk.jpg
HTTP/1.1 200 OK
...
Accept-Ranges: bytes
Content-Length: 146515
在如上响应中,Accept-Ranges: bytes 代表可以使用字节作为单位来定义请求范围。这里的 Response Headers中的 Content-Length: 146515 则代表该资源的完整大小。
如果站点响应中未返回 Accept-Ranges 响应头,或者其值为none,那么这意味着server不支持HTTP range请求。
我们可以对一个资源发起单个范围请求:
curl http://i.imgur.com/z4d4kWk.jpg -i -H "Range: bytes=0-1023"
发出的请求如下:
GET /z4d4kWk.jpg HTTP/1.1 Host: i.imgur.com Range: bytes=0-1023
正常情况下 server 返回 206 部分内容响应:
HTTP/1.1 206 Partial Content Content-Range: bytes 0-1023/146515 Content-Length: 1024 ... (binary content)
这次并非检查server是否支持range请求,故Content-Length表示的是现在请求的范围大小,而Content-Range则表示的是这部分消息在完整资源中的位置。
curl http://www.example.com -i -H "Range: bytes=0-50, 100-150"
用逗号隔开多个范围,即可同时请求多部分资源。
响应如下:
HTTP/1.1 206 Partial Content Content-Type: multipart/byteranges; boundary=3d6b6a416f9b5 Content-Length: 282 --3d6b6a416f9b5 Content-Type: text/html Content-Range: bytes 0-50/1270
该响应有:
每个部分包含自己的Content-Type 和 Content-Range
当继续请求更多资源时,你需要确保被存储的资源在上一帧收到后没有被改变。
If-Range HTTP请求创建了一个带条件的range HTTP请求,如果条件得到满足,range请求将会被发出,server 发回带有适当正文的206 partial content 应答,如果条件不满足则返回完整资源,并显示200 OK状态。这个头可以与Last-Modified 验证程序,或者与 ETag 一起使用。
If-Range: Wed, 21 Oct 2015 07:28:00 GMT
在处理HTTP Range 请求时,有三个相关的状态:
Transfer-Encoding 请求头允许分块编码,这在服务器给客户端发送大量的数据,且响应总大小直到请求结束才能确定时很有用,如果服务器直接发送数据给客户端而不缓存响应,或者确定具体响应大小的话,会产生延迟。HTTP Range 请求和分块是兼容的,一起用或者不一起用均可。
天这篇文章和大家聊一聊如何做到只请求资源的一部分,这里需要用到几个http头——range、if-range、content-range、accept-range。
Range主要用来设置获取数据的范围,格式如下:
Range: <unit>=<range-start>-<range-end>
Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>, <range-start>-<range-end>
如: 获取 0-10字节的数据和15到结尾的数据
Range: bytes=0-10,15-
If-Range主要用来判断是否满足范围请求的条件,举个例子,假设昨天你用迅雷下载了一部电影但是没有下载完,今天你要接着下载,当再次下载时客户端就需要和服务器验证这部电影的资源内容有没有发生变化,If-Range在这里就是做验证使用的 。
Content-Range表示响应数据的内容范围,语法格式如下:
Content-Range: <unit> <range-start>-<range-end>/<size>
Content-Range: <unit> <range-start>-<range-end>/*
Content-Range: <unit> */<size>
例如:
Content-Range: bytes?10-15/22
Accept-Ranges用于服务器响应,告诉浏览器是否支持Range,
语法:
Accept-Ranges: bytes
Accept-Ranges: none
上面介绍了几个头信息的概念,下面我们用代码实现一下,大概流程如下:
图1
我们还是以中间件的方式去实现。
图2
如图2,我们通过range头获取请求的范围信息,如果类型合法,我们还需要处理范围数据,处理方式和处理url的query一样,在处理的过程中我们需要对不合法的范围进行纠正和过滤。如果类型不合法,我们就正常返回整个内容。
对于range范围内重叠和相邻的区域可以做一次合并,例如:
bytes=50-55,0-10,5-10,56-60,可以合并为[{start: 0, end: 10},{start: 50, end: 60}]。
图3
如图3,如果range范围无效,我们返回状态码416,告诉客户端range是无效的,不满足要求。
图4
如图4,如果range范围校验也没问题,我们还需要通过if-range提供的信息与etag或者Last-Modified做对比(对比二选一)。
如果不满足if-range条件,继续走正常返回资源的逻辑,如果满足那就开始返回部分资源。
图5
如图5,设置了状态为206,这是http标识部分内容返回的状态,另外还设置了accept-range和content-type。此处我们使用stream对内容进行分片,这里只返回了一段范围的内容。
对于多段请求,也是可以实现的,如下:
图6
需要把content-type设置成multipart/byteranges; boundary=分隔符,这样的话就可以分片下载了。
这篇文章主要介绍了range头相关的使用方法,内容还是蛮多的。本文的代码实现没那么全,主要讲了一下原理及流程,小伙伴们如果需要使用可以再打磨一下。
Hypertext Transfer Protocol,超文本传输协议,和HTML(Hypertext MarkupLanguage 超文本标记语言)一起诞生的,用于在网络上请求和传输HTML内容。
超文本,也就是扩展文本,指的是HTML中可以有链向别的文本的链接(hyperlink)。
浏览器:
用户输入地址回车或点击链接->浏览器拼装HTTP报文并发送请求给服务器->服务器处理请求后发送响应报文给浏览器->浏览器解析响应报文并使用渲染引擎显示到界面
手机App:
用户点击或界面自动触发联网需求->Android代码调用拼装HTTP报文并发送请求到服务器->服务器处理请求后发送响应报文给手机->Android代码处理响应报文并作出相应处理(如储存数据、加工数据、显示数据到界面)
URL格式
三部分:协议类型、服务器地址(和端口号)、路径(Path)
协议类型://服务器地址[:端口号]路径
例如:http://toutiao.com/users?gender=male
报文格式
请求报文
响应报文
GET
对应Android Retrofit的代码
POST
对应Retrofit的代码:
PUT
对应Retrofit的代码:
DELETE
HEAD
Status Code状态码
三位数字,用户对响应结果做出类型化描述(如获取成功,内容未找到)。
作用:HTTP消息的metadata。
Host
目标主机。注意:不是在网络上用于寻址的,而是在目标服务器上用于定位子服务器的。
Content-Type
指定Body的类型,主要有四类:
请求Web页面是返回响应的类型,Body中返回html文本。格式如下:
Web页面纯文本表单的提交方式。
格式如下:
对应Retrofit的代码
Web页面含有二进制文件时的提交方式。
格式如下:
对应Retrofit的代码:
单项内容(文本或非文本都可以),用于Web Api的响应或者POST/PUT的请求
请求中提交JSON
对应Retrofit的代码
响应中返回JSON
请求中提交二进制内容
对应Retrofit的代码
相应中返回二进制内容
指定Body的长度(字节)。
Transfer:chunked(分块传输编码Chunked Transfer Encoding)
用于当响应发起时,内容长度还没能确定的情况下。和Content-Length不同时使用。用途是尽早给出响应,减少用户等待。
格式:
指定重定向的目标URL
用户代理,即是谁实际发送请求、接受响应的,例如手机浏览器、某款手机App。
按范围取数据
Accept-Range:bytes响应报文中出现,表示服务器支持按字节来取范围数据
Range:bytes=<start>-<end>请求报文中出现,表示要取哪段数据
Content-Range:<start>-<end>/total响应报文中出现,表示发送的是哪段数据
作用:断点续传、多线程下载。
作用:在客户端或中间网络节点缓存数据,降低从服务器数据的频率,以提高网络性能。
REST的定义众说纷纭,没有统一答案。
个人认为:REST HTTP即正确使用HTTP。包括:
1.【单选题】用户在浏览器地址栏输入地址后回车,一段时间后浏览器显示出页面,这背后发生了什么?
A. 浏览器拼装 HTTP 报文并向服务器请求 -> 服务器处理请求并返回响应报文 -> 浏览器接收到响应报文后处理并使用渲染引擎来渲染出界面
B. 浏览器把地址栏的 URL 发送给服务器 -> 服务器把 URL 对对应的页面图片文件发回给浏览器 -> 浏览器接收到图片后显示出来
2.【单选题】一个 URL 如 http://api.qq.com/user/1 中,对于「HTTP 组装报文」来说可以拆成哪几部分
A. ① 【http:】-> 协议类型 ② 【//api.qq.com/user/1】-> 路径
B. ① 【http:】-> 协议类型 ② 【//api.qq.com】-> 服务器地址 ③ 【/user/1】-> 路径
C. ① 【http:】-> 协议类型 ② 【//api.qq.com/user/】-> 路径 ③ 【1】-> 文件名
3.【单选题】HTTP 的请求报文分为哪几部分?
A. 请求行、path、Headers、Body
B. 请求行、Headers、Body
C. 请求行、方法、Host、Body
4.【单选题】请求行由哪三部分组成?
A. method、path、HTTP 版本
B. method、path、Host
C. method、服务器地址、path
5.【单选题】HTTP 的响应报文分为哪几部分?
A. 响应头、响应码、响应信息
B. 状态行、响应头、Headers、Body
C. 状态行、Headers、Body
6.【单选题】响应报文的状态行由哪三部分组成?
A. HTTP 版本、API 版本、状态码
B. HTTP 版本、状态码、状态信息
C. HTTP 版本、Body 类型、状态码
7.【多选题】以下哪几项符合 GET 方法?
A. 用于获取资源A
B. 用于增加或修改资源
C. 仅用于修改资源
D. 用于删除资源
E. 幂等(即反复调用多次时会得到相同的结果)E. 幂等(即反复调用多次时会得到相同的结果)
F. 请求报文中包含 BodyF. 请求报文中包含 Body
8.【多选题】以下哪几项符合 POST 方法?
A. 用于获取资源A. 用于获取资源
B. 用于增加或修改资源B. 用于增加或修改资源
C. 仅用于修改资源C. 仅用于修改资源
D. 用于删除资源D. 用于删除资源
E. 幂等(即反复调用多次时会得到相同的结果)E. 幂等(即反复调用多次时会得到相同的结果)
F. 请求报文中包含 BodyF. 请求报文中包含 Body
9.【多选题】以下哪几项符合 PUT 方法?
A. 用于获取资源A. 用于获取资源
B. 用于增加或修改资源B. 用于增加或修改资源
C. 仅用于修改资源C. 仅用于修改资源
D. 用于删除资源D. 用于删除资源
E. 幂等(即反复调用多次时会得到相同的结果)E. 幂等(即反复调用多次时会得到相同的结果)
F. 请求报文中包含 BodyF. 请求报文中包含 Body
10.【多选题】以下哪几项符合 DELETE 方法?
A. 用于获取资源A. 用于获取资源
B. 用于增加或修改资源B. 用于增加或修改资源
C. 仅用于修改资源C. 仅用于修改资源
D. 用于删除资源D. 用于删除资源
E. 幂等(即反复调用多次时会得到相同的结果)E. 幂等(即反复调用多次时会得到相同的结果)
F. 请求报文中包含 BodyF. 请求报文中包含 Body
11.【单选题】Host 这个 Header 的作用是?
A. 在网络上寻址目标主机的 IP,并在找到目标主机后确认主机域名和端口
B. 仅用于寻址目标主机的 IP
C. 仅用于找到目标主机后确认主机域名和端口
12.【单选题】Content-Type 为 x-www-form-urlencoded 时,请求报文中 Body 的格式为以下哪种形式?
A. Encoded URL,即 name1=value1&name2=value2 的形式
B. 分多个部分传输每部分内容的形式,使用 boundary 对它们进行分隔
C. JSON 形式,如 {"name1":value1,"name2":value2}
13.【单选题】Content-Type 为 multipart/form-data 时,请求报文中 Body 的格式为以下哪种形式?
A. Encoded URL,即 name1=value1&name2=value2 的形式
B. 分多个部分传输每部分内容的形式,使用 boundary 对它们进行分隔
C. JSON 形式,如 {"name1":value1,"name2":value2}
14.【单选题】Content-Type 为 application/json 时,请求报文中 Body 的格式为以下哪种形式?
A. Encoded URL,即 name1=value1&name2=value2 的形式
B. 分多个部分传输每部分内容的形式,使用 boundary 对它们进行分隔
C. JSON 形式,如 {"name1":value1,"name2":value2}
答案:ABBACBABBDAABCB
*请认真填写需求信息,我们会在24小时内与您取得联系。