网络编程——Http 断点续传

本文详细介绍了HTTP断点续传的原理,包括HTTP/1.1协议中支持的Range和Content-Range报头域的使用,以及206 Partial Content响应状态码的意义。通过Range指定下载范围,实现文件的分块下载,从而支持断点续传。同时讨论了If-Range报头域在确保文件未被修改时进行续传的情况。

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头部显示当前片段响应体在完整包体中的位置。


 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值