http断点续传原理
断点续传,就是从文件已下载完成的地方起始继续下载。最早HTTP 协议是不支持断点续传的,从HTTP/1.1 开始支持。
HTTP1.1 协议开始支持获取文件的部分内容,这为并行下载和断点续传提供了技术支持。它是通过在 Header 里两个参数实现的,客户端发请求时带报头域 Range ,服务器响应时带报头域 Content-Range。
在客户端发出带 Range报头域的请求后,服务器会在响应报头中带Content-Range 返回,表面当前接受的范围和文件总大小。
而在响应完成后,返回的响应头内容也不同:
HTTP/1.1 200 Ok(不使用断点续传方式)
HTTP/1.1 206 Partial Content(使用断点续传方式)
相关报头
断点下载时才用到的Range 和 Content-Range 实体报头。
Range
在请求头中使用,指定下载范围的第一个字节的位置和最后一个字节的位置,一般格式:
Range:(unit=first byte pos)-[last byte pos]
请求下载整个文件:
GET /testMovie.rar HTTP/1.1
Connection: close
Host: 106.1.229.219
Range: bytes=0-1025 //请求下载整个文件,可以是bytes=0- 或不用这个头
一般正常回应
HTTP/1.1 200 OK
Content-Length: 1025
Content-Type: application/octet-stream
Content-Range: bytes 0-1024/1025 //文件总大小是 1025
把文件分割成4个部分,创建4个线程,每个线程下载一个部分,如果文件大小为409个byte,那么分割方式可以为:0-99 (前100个字节),100-199(第二个100字节),200-299(第三个100字节),300-408(最后109个字节)。
分割完成,每个线程都有自己的任务,比如线程3的任务是下载200-299部分文件,我们使用HTTP1.1的Range头。Range报头域可以请求实体的一个或者多个子范围,Range计算字节数是从0开始的 ,Range的值为0表示第一个字节:
表示头500个字节:Range: bytes=0-499
表示第二个500字节:Range: bytes=500-999
表示最后500个字节:Range: bytes=-500
表示500字节以后的范围:Range: bytes=500-
第一个和最后一个字节:Range: bytes=0-0,-1
同时指定多个范围:Range: bytes=500-600,601-999
请求报文 :
Range: bytes=200-299
保证只请求文件的200-299字节
服务器接收到该请求报文,发现这是一个带有Range头的GET请求,服务器的响应报文:
HTTP/1.1 206 OK //表示处理请求成功。
Content-Range: bytes 200-299/403 // 斜杠后面的403表示原文件的总大小
Content-Range
用于响应头,在服务器向客户返回一个部分响应,它描述响应覆盖的范围和整个实体长度。一般格式:
Content-Range: bytes (unit first byte pos) - [last byte pos]/[entity legth]
通常Content-Range的用法为:
第一个500字节
Content-Range: bytes 0-499/1234
第二个500字节
Content-Range: bytes 500-999/1234
除去第一个500字节
Content-Range: bytes 500-1233/1234
最后500字节
Content-Range: bytes 734-1233/1234
服务器通过Accept-Range头部表示是否支持Range请求
Accept-Ranges = acceptable-ranges
例如:
Accept-Ranges: bytes: 支持;
Accept-Ranges: none: 不支持
返回状态码
如果只获取部分的body,那么服务器端返回的响应码不是200,而是206。
206 Partial Content
Content-Range头部:显示当前片段响应体在完整包体中的位置
Content-Range = byte-content-range /DIGIT
DIGIT // 完整资源的大小,如果未知则用*号替代
例如:
1、Content-Range: bytes 42-1024/1025
2、Content-Range: bytes 42-1024/*
用一个视频播放的例子来看看206响应的样子。
416 Range Not Statisfiable
如果获取范围超出实际资源的大小。返回416
服务器不支持Range请求的话,则返回状态码200并返回完整的响应包体
增强校验
终端发起续传请求时,URL对应的文件内容在服务器端已经发生变化,此时续传的数据是错误的。
如何判断续传文件时是否已经发生过改动。
If-Range报头域
If-Range 可以使用上次响应报头的 Etag 或者 Last-Modified 返回的值。
如果请求报文中没有 Range,那么 If-Range 就会被忽略。
如果服务器不支持 If-Range,那么 Range 也会被忽略。
例如:
If-Range: “gghty4d648041f6b80”
If-Range: Wed, 18 Feb 2017 12:15:07 GMT
如果请求报文中的 Etag 与服务器目标内容的 Etag 相等,即没有发生变化,那么应答报文的状态码为 206。如果服务器目标内容发生了变化,那么应答报文的状态码为 200,并且返回全部的文件内容。
总结
- 客户端通过Range头传递请求范围,客户端按范围下载,在Range报头域的格式为Range: bytes=0-100, 200-300…(用逗号分隔)
- 服务端返回Accept-Range头部表示是否支持Range请求。
- 对于只获取部分body的请求,服务器返回响应码206,其中Content-Range头部显示当前片段响应体在完整包体中的位置。
本文详细介绍了HTTP断点续传的原理,包括HTTP/1.1协议中支持的Range和Content-Range报头域的使用,以及206 Partial Content响应状态码的意义。通过Range指定下载范围,实现文件的分块下载,从而支持断点续传。同时讨论了If-Range报头域在确保文件未被修改时进行续传的情况。
4794

被折叠的 条评论
为什么被折叠?



