断点续传的原理及实现

一、 简单原理

说到断点续传,就不得不说一些和断点续传相关的HTTP头部字段。

① Content-Length

Content-Length用于指示HTTP响应包中实体的大小。除非使用了分块编码,否则Content-Length首部就是带有实体主体的报文必须使用的。使用Content-Length首部是为了能够检测出服务器崩溃而导致的报文截尾,并对共享持久连接的多个报文进行正确分段。

  • 检测结尾
  1.  HTTP的早期版本采用关闭连接的办法来划定报文的结束。但是,没有Content-Length的话,客户端无法区分到底是报文结束时正常的关闭连接还是报文传输中由于服务器崩溃而导致的连接关闭。客户端需要通过Content-Length来检测报文截尾。
  2.  报文截尾的问题对缓存代理服务器来说尤为重要。如果缓存服务器收到被截尾的报文却没有识别出截尾的话,它可能会存储不完整的内容并多次使用他来提供服务。缓存代理服务器通常不会为没有显式Content-Length首部的HTTP主体做缓存,以此来减小缓存已截尾报文的风险。
  • Content-Length与持久连接
  1. Content-Length首部对于持久链接是必不可少的。如果响应通过持久连接传送,就可能有另一条HTTP响应紧随其后。客户端通过Content-Length首部就可以知道报文在何处结束,下一条报文从何处开始。因为连接是持久的,客户端无法依赖连接关闭来判断报文的结
  2. 有一种情况,使用持久连接可以没有Content-Length首部,即采用分块编码(chunked encoding)时。在分块编码的情况下,数据是分为一系列的块来发送的,没块都有大小说明。哪怕服务器在生成首部的时候不知道整个实体的大小(通常是因为实体是动态生成的),仍然可以使用分块编码传输若干已知大小的块。

② Transfer-Encoding

HTTP协议中只定义了一种Transger-Encoding,也就是chunked举个例子,如果服务端的主体是动态生成的。而客户端不希望服务端将主体全部生成后再获取,因为中间的时延会特别大chunked的格式如下:

③ Content-Enconding

常见有如下三种:gzip,deflate,compress。它用来指示实体是以什么算法进行编码的。通常,Content-EncodingTransfer-Encoding结合使用。

④ Content-Range

用于响应头,指定整个实体中的一部分的插入位置,他也指示了整个实体的长度。在服务器向客户返回一个部分响应,它必须描述响应覆盖的范围和整个实体长度。一般格式:

Content-Range: bytes start-end/total

⑤ Range

用于请求头中,指定第一个字节的位置和最后一个字节的位置,一般格式:

Range:bytes=start-end

 

二、单线程实现

① 是否支持断点续传

  • 采用head获取部分实体,看是否返回头中含有Content-Range
  • 采用head获取部分实体,看返回状态码是否为206。

② 具体实现步骤

  • 使用head方法获取文件大小
  • 获取本地文件大小
  • 设置请求头Range信息
  • 利用requqests.response.iter_content以及开启stream模式
  • 文件下载到一定大小就写入

三、多线程实现(非断点续传)

 

四、多线程断点续传

这就是上面的结合体,不过通常会使用一个配置文件用于保存下载的状态,重新下载的时候就根据此文件重新配置。

 

此条目发表在程序学习分类目录,贴了, , 标签。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。 必填项已用*标注