前几天一个同事跑过来找我说,我们在广告素材视频这块想做断点续传,就是这次某个视频缓存到一半,下次不用重头开始,可以在原来停留得位置开始继续下载.以提供更好的用户体验。

同时说需要我们支持吐素材地址的业务接口告诉终端最后修改时间/文件签名(md5),用这个用来判断我当前要下的文件有没有变化,同时告诉终端文件的Size大小.

我一细想,这个问题压根不需要通过改变现有接口提供更多的数据来做.下面从原理实现上简单说下:

关键点:

对于断点续传,关键点是两个:

1. 终端知道当前的文件和上一次加载的文件是不是内容发生了变化,如果有变化,需要重新从offset 0 的位置开始下载

2. 终端记录好上次成功下载到的offset,告诉server端,server端支持从特定的offset 开始吐数据

文件变化感知:

前置业务接口方案:

对于关键点1,对于决定大部分产品的业务场景,可以通过前置业务接口解决;这里简单介绍一下:

对于非下载工具类的产品,如视频APP(奇艺,优酷),视频播放前会请求相关业务的信息,主要返回片子叫什么名字,主要演员等等一些列信息,同时会返回一个对于播放最重要的信息——播放地址。

播放地址就是我们可以做文章的地方,如果《太子妃第一集》这个片子更新了(被广电要求减掉某个污的画面),可以后端系统让这个业务接口吐不同的播放地址/一个不同的url参数(?ver=1.1)/位置参数(#ver1.1)。这样纯天然的URL变化能纯天然的让终端认为不是同一个片子,而需要重新加载。

HTPP 标准ETAG方案:

没有业务接口的下载工具类的如何解决呢?

下载工具类的没有前置接口,可以使用HTTP 的ETAG来标识是否文件已经修改。

ETAG原理:如果URL上的资源内容改变,一个新的不一样的ETag就会被分配。用这种方法使用ETag即类似于指纹,并且他们能够被快速地被比较,以确定两个版本的资源是否相同。ETag的比较只对同一个URL有意义——不同URL上的资源的ETag值可能相同也可能不同,从他们的ETag的比较中无从推断。

ETAG是HTTP的一个可选字段,且没有规范他的实现;实际上业内用的比较多的就是使用MD5签名的方式来生成(linux shell md5sum)

典型用法:

server端: Nginx >1.3.3 自带有ETAG的module , 当然同时也可以在业务代码里SetHeaders加一个ETAG字段

client端:

第一次请求时:

String etag = httpURLConnection.getHeaderField("ETag");

ETag: "b428eab9654aa7c87091e"

第二次请求(断点续传时):

httpURLConnection.setRequestProperty(“If-None-Match”, "b428eab9654aa7c87091e");

If-None-Match: "b428eab9654aa7c87091e"

如果ETag值匹配,这就意味着资源没有改变,服务器便会发送回一个极短的响应,包含HTTP “304 未修改”的状态。304状态告诉客户端,它的缓存版本是最新的,并应该使用它。

然而,如果ETag的值不匹配,这就意味着资源很可能发生了变化,那么,一个完整的响应就会被返回,包括资源的内容,就好像ETag没有被使用。这种情况下,客户端可以用新返回的资源和新的ETag替代先前的缓存版本。

续传支持:

对于一个C/C++程序员,第一时间会得出一个系统级实现方案:

1. 客户端传当前的offset

2. server端seek到文件特定的offset开始读取往http connection吐数据

不过我们深处在一个开放方案和标准不断完善的时代,不需要自己实现一个(这也是像我这样的C/C++研发工程师越来越没落的原因),来看看HTTP协议是怎么解决这个问题的:

HTTP头Range字段:

Range : 用于客户端到服务器端的请求,可通过该字段指定下载文件的某一段大小,及其单位。典型的格式如:

Range: bytes=0-499 下载第0-499字节范围的内容
Range: bytes=500-999 下载第500-999字节范围的内容
Range: bytes=-500 下载最后500字节的内容
Range: bytes=500- 下载从第500字节开始到文件结束部分的内容

来个简单粗暴的例子

curl --header "Range: bytes=0-20000" xxx.com/memcache.pdf -o part1
curl --header "Range: bytes=20001-223651" xxx.com/memcache.pdf -o part2
cat part1 part2 >> a.pdf

衍生阅读:

使用ETags减少Web应用带宽和负载

HTTP文件断点续传的原理的更多相关文章

  1. 文件断点续传原理与实现—— ESFramework 通信框架4.0 进阶(12)

    在ESFramework通信框架 4.0 快速上手(13) -- 文件传送,如此简单一文的详细介绍和ESFramework通信框架 4.0 快速上手(14) -- 聊天系统Demo,增加文件传送功能( ...

  2. .net断点续传的原理

    在了解HTTP断点续传的原理之前,先来说说HTTP协议,HTTP协议是一种基于tcp的简单协议,分为请求和回复两种.请求协议是由客户机(浏览器)向服务器(WEB SERVER)提交请求时发送报文的协议 ...

  3. 客户端HTTP断点续传的原理

    其实断点续传的原理很简单,就是在Http的请求上和一般的下载有所不同而已. 打个比方,浏览器请求服务器上的一个文时,所发出的请求如下:假设服务器域名为wwww.scu.edu.cn,文件名为down. ...

  4. ASP.NET用HttpListener实现文件断点续传

    本文转载:http://www.cnblogs.com/TianFang/archive/2007/01/03/610739.html 断点续传的原理很简单,就是在Http的请求和应答的报文头上和一般 ...

  5. 浅谈文件断点续传和WebUploader的基本结合

    0.写在前面的话 上篇博客已经是在8月了,期间到底发生了什么,只有我自己知道,反正就是心情特别糟糕,生活状态工作状态学习状态都十分不好,还有心思进取吗,No!现在状态好起来了,生活又充满了希望 :D  ...

  6. PHP 实现断点续传的原理和方法

    PHP 实现断点续传的原理和方法 0. http协议从1.1开始支持静态获取文件的部分内容,为多线程下载和断点续传提供了技术支持.它通过在Header里两个参数实现的,客户端发请求时对应的是Accep ...

  7. Linux下文件删除的原理

    Linux文件删除的原理: Linux是通过link的数量来控制文件的删除的,只有当一个文件不存在任何link的时候,这个文件才会被删除,一般来说每个文件都有2个link计数器:i_count和i_n ...

  8. iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载+使用输出流代替文件句柄

    前言:本篇讲解,在前篇iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载的基础上,使用输出流代替文件句柄实现大文件断点续传.    在实际开发中,输入输出流用的比较少,但 ...

  9. Spring Boot 文件上传原理

    首先我们要知道什么是Spring Boot,这里简单说一下,Spring Boot可以看作是一个框架中的框架--->集成了各种框架,像security.jpa.data.cloud等等,它无须关 ...

随机推荐

  1. 【BOOM】一款有趣的Javascript动画效果

    实践出真知,有的时候看到一些有趣的现象就想着用自己所学的知识复现一下.    boomJS 缘起 前几天在 github 上看到同事的一个这样的小项目,在 IOS 上实现了这样一个小动画效果,看上去蛮 ...

  2. 剑指Offer面试题:12.在O(1)时间删除链表结点

    一.题目:在O(1)时间删除链表结点 题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点. 原文采用的是C/C++,这里采用C#,节点定义如下: public class ...

  3. Step by Step 创建一个新的Dynamics CRM Organization

    原创地址:http://www.cnblogs.com/jfzhu/p/4012833.html 转载请注明出处 前面演示过如何安装Dynamics CRM 2013,参见<Step by st ...

  4. Module-Zero之组织单元(OU)管理【新增】

    返回<Module Zero学习目录> 概览介绍 OrganizationUnit实体 OrganizationUnit管理者 公共用例 设置 概览介绍 组织单元(Organization ...

  5. linux添加自定义的命令!

    修改了/root/下的.bashrc -bash-4.1# vi .bashrc # .bashrc # User specific aliases and functions alias rm='r ...

  6. c# 文件属性读取操作及文件之间操作

    c# 获取文件最后修改日期代码FileInfo f = new FileInfo(@"c:\1.txt");Console.WriteLine(f.LastWriteTime.To ...

  7. Constraint4:default约束

    Default约束的作用是在insert语句执行时,如果未显式给指定的column赋值,那么使用默认值给column赋值:如果在Insert命令中显式为指定的Column赋值,那么将插入显式值.每一列 ...

  8. 用Mindjet MindManager 15 打开文件后停止响应的解决方法

    这个是因为文件里面有很多规格不统一的注释(那个像小本子的图标[里面就是注释部分]),默认编码是utf-8的,如果不一样的话就会出现这个问题.网上大多数都是让咱们删掉注释再打开 弱弱的问一下,如果我都把 ...

  9. 【已解决】WinPhone模拟器报错:模拟器没法确定来宾虚拟机通信的主机ID地址。某些功能已被禁用

    先看警告 再看错误信息 计算机管理打不开就==>Win+R ==>compmgmt.msc 发现,dnt在管理员权限组里面,也在Hyper-V权限组里面 看看Hyper-V的驱动有木有被禁 ...

  10. js立即执行函数

    一.JS立即执行函数的写法 方式1.最前最后加括号 (function(){alert(1);}()); 方式2.function外面加括号   (function(){alert(1);})(); ...