在开发中经常需要上传下载文件,涉及web页面,手机应用,线下服务器等,文件传输方式有HTTP,FTP,BT。。于是基于HTTP开发了统一文件上传下载接口。
由于上传涉及多端,网络状况复杂,需要能够支持断点续传,因此需要对文件进行分块和校验。
请求上传:
- chunk:当前块编号
- chunks:文件分块总数
- md5:整个文件md5
- content:文件块内容
- size:文件块大小
服务端返回:
- statu:状态,0失败,非0成功
- chunk:需要上传的块编号
- message:操作信息
服务端有几种情况
- 1. 上传成功,md5已经存在,说明文件已存在,则返回上传成功,并结束上传,类似秒传
- 2. 上传成功,md5已经不存在,但当前文件块已经存在,说明该文件已经上传过一部分,则返回成功,并给出需要开始上传的块号,类似断点续传
- 3. 上传成功,文件块不存在,当前块号小于总块数减一,则返回上传成功,并给出下一块块号
- 4. 上传成功,文件块不存在,当前块号等于总块数减一,进行合并,校验成功,则返回上传成功,并结束上传
- 5. 上传成功,文件块不存在,当前块号等于总块数减一,进行合并,校验成功,则返回上传失败,从第一块重新开始上传
- 6. 上传失败,服务端返回失败,则根据错误信息重传
- 7. 上传失败,服务端没有返回,则重传当前块
客户端依据自定义的大小对文件进行切割,每次传递一个块,当服务端接收到当前块号为总块数减一则认为全部上传完毕,进行文件块合并,清除临时文件块,计算MD5,如果MD5与传递过来的相等则认为上传成功,否则失败,要求客户端从第一块重传。
这个是基于客户端顺序上传的,假如是并发上传呢?那么就需要在每个分块上传结束后触发合并,需要借助锁来管理。
又拍云表单分块上传则分为3步骤:
- 1.初始化,上报文件信息
- 2.上传分块
- 3.上传结束,触发合并
而百度的WebUploader则支持浏览器向服务端的断点续传,利用HTML5或Flash对文件进行分块,计算MD5。
HTTP分块下载,也就是断点续传下载,是根据HTTP1.1协议(RFC2616)中定义的HTTP头 Range和Content-Range字段来控制的:
- 1. 客户端在HTTP请求头里面指明Range,即开始下载位置
- 2. 服务端在HTTP响应头里面返回Content-Range,告知下载其实点和范围
服务端可以将文件MD5等加入Etag或自定义Header字段里面,HTTP客户端便可以分开请求数据,最后合并;否则永远都是从头开始。其实也可以把大文件切成多个小文件,再一个个下载回来合并。
有些web服务器直接支持文件上传和下载的断点续传,比如Nginx。
刚才的文件分块传输过程,有点像TCP通信,也有建立连接,分片,校验,重发,断开连接。
而这个将大任务分解为多个小任务进行处理的思想,即准备–>循环(并行)处理–>结束,可以应用到很多项目里面,比如大数据,爬虫。为Web管理系统写了jQuery插件用来处理的耗时任务,将一个耗时任务分解为多个循环请求,避免超时
- 1. prepare:服务端返任务标示ID,总步骤,及附加参数
- 2. process:根据返回参数进行循环请求
- 3. complete:循环完成,触发结束
后面又延伸出另外一个插件,支持任意顺序步骤的处理。
参考链接:
聊聊大文件上传
md5 javascript
HTTP协议--断点续传
http断点续传的秘密
nginx-upload-module模块实现文件断点续传
通过curl测试服务器是否支持断点续传
Pingback引用通告: TCP UDP探索 | 勇气