关于 断点续传上传与秒传 你绕不过去的坎 html5+php

qq_34028302 2016-02-23 07:48:27
加精

超大文件上传就无法避免断点上传,想要实现秒传你就饶不开文件特征。本文不涉及具体代码。只讲我自己对断点上传于秒传的学习经验。
首先我们分析一下要实现断点续传于秒传的具体要点。

1、前端拆分碎片
2、前端生成文件特征
3、传输过程
4、后台接收文件合并
5、合并完成后,后台的特征对比

看似原理简单,粗狂分析一下就可以动手了,其实每一步都有很多技术难点于陷阱。

1、前端拆分文件碎片

在以前只要断点续传就必须采用前端控件。控件主要工作就是在拆分文件与碎片与分析md5。现在的html5本身已经支持对文件拆分读取上传。至于如何拆分自己搜索一下很容易找到demo。这里陷阱不多只要考虑一下兼容性就可以了,IE系列可以考虑用flash。

2、前端生成文件特征

这里说明一下,我没有直接说是md5 是因为md5现在在大型网盘项目里碰撞的几率已经很高了,不能完全依赖md5,尽量多取几种哈西值一起传到后端做特征。(取文件的几部分做特征是很不靠谱的不用考虑了)

在前端生成特征才能实现秒传功能(也许有不需要的方法反正我不知道)。文件生成哈西值,是采用流运算方式把整个文件读取分析一遍。由于需要读取,那么超大文件的耗时是不可避免的。目前js 有个很好的库类可以支持采用文件流方式计算md5 。spark-md5.js 这是个好东西。只需要把文件碎片挨个分析一遍,文件全部跑完就能生成一个md5了理论上可以生成任意大小文件的md5。测试过8G的文件生成一个md5码需要十几分钟。这取决于客户机器性能和磁盘速度。网上还有其他哈西的文件流获取算法,请自行百度。

3、传输

传输现在html5现在可以采用ajax和websocket两种方式可以任选。这里我选用的是自己熟悉的ajax方式,websocket只是初略的看了一下。就不发表具体看法了。
ajax生成传输队列的时候有个坑需要注意一下。当拆分碎片上传,也就是每一个碎片是一个ajax请求。那么一个8G的文件将会生成多少请求呢。一个循环下去浏览器死了。所以要采用递归方式进行控制ajax堵塞数量。一次循环传输10个碎片,传完在传下一组。

4、后台的文件合并。
接收到文件就需要考虑合并问题了。我之前百度了一下。基本都告诉我等待文件碎片全部上传完成然后合并。当我上传一个8G的文件到后台后然后循环合并,太恐怖了上万的碎片合并。想想就难受。
第一个想法是放到队里里在后面慢慢跑。后来放弃了感觉体验不是很好。
后来想到了边上传边合并,把合并时间分散到每一个请求里。每个请求只处理1-2mb的碎片还是很快的。
刚开始参考迅雷想生成一个和目标文件体积相等的空白文件。然后等待碎片来拼入文件。后来发现php不能快速干这个事情。有其他方法也懒着研究了。就写了一个扩容算法
算法说明:
收到请求后如果第一个碎片是2号,那么在生成的文件里填充字符串把1号碎片的位置留下,然后写入2号碎片,等1号碎片 达到,在把1号碎片写入他自己的位置。

算法基本上很快没有什么延时。好在我们不是做下载,上传时不会直接收到最后的碎片。

写好后进行测试发现文件大于2g就不在生成了。块是很快了不过不能处理大文件。后来发现是php文件指针在32位系统下最大值是2G。如果移动大于2G 就会返回-1失败。那么理论上这个算法最大生成文件是2G。(或者是4G ,指针从文件尾巴向前计算还有2g不过我没有继续研究下去,理论上php读取文件内容最大值是4G)下面换一种算法。

最简单的办法,就是往文件尾巴里追加内容,这样就不受文件指针大小影响了。ajax 在并发的时候到达顺序是不一样的。但是这个不影响,不会对我们后台编程产生太大的障碍。后台进行搬砖一样的排序写入就好了,。
举例:
如果是第一个碎片收到的是2号,那么把碎片文件拷贝出来备用。
下一个请求碎片如果是1那么写入文件,写入后询问备用里有没有2号如果有写入。以此类推。

这个算法和上面的扩容方法比起来效率要低了一些。因为要做计数器和询问利用。但是影响不是很大。
我两种算法都采用了如果文件小于1.99g用上面得扩容算法,大于就用排序。
合并也完成了剩下就是对结果进行效验了。

5、后台文件效验。
不要相信 php 或者其他语言的 md5_file这玩意处理不来大文件。几个G基本上就崩溃了。记住一点只要你想获得文件的md5 ,就必须对这个文件进行读取分析一遍才行怎么做都是很耗时的。
像百度那种大型网盘已经完成对TB级别md5随时生成,真的很牛叉。后来我分析了一下他们应该是这么做的。

应该和我们处理文件合并的方式差不多。把计算md5的时间分摊到了每一个碎片上。我们可以这么理解,md5 需要顺序分段读取整个文件进行分析才能生成一个md5值,那么我们在上传过程中每一个碎片都是文件的一部分。我们只要顺序分析每一个文件碎片,那么上传完成了md5也就生成了(理论上也能到TB级别)。

我尝试用这种方式找了一个php 版本的md5算法,改进了一下,实现了超级大文件上传完成后台即使获得到md5的类。(测试过与 md5_file函数获得的值一样.)
经过测试完全可行。 "但是,可但是,但可是" php真的不适合干这种大型纯运算很慢,基本上js 算md5的效率 是php几十倍。一个2mb的碎片计算需要9秒左右。
这么做每一个碎片后台响应时间都超长,也就直接影响上传速度了。
几经研究无果。决定放弃php 找师哥用c写个扩展来干这个事情了。

项目基本完成了,至于其他的续传 和 秒传 没什么好讲的,你都已经有碎片了续传不是问题。你都能获得前后端特征码了,那么秒传也不是问题了。


这个过程最耗时的是前端计md5,其他运算都分摊到每一碎片上了。



上面的东西没有经过大小项目验证全是理论上的,也许我是错的。我说的都是我自己理解的有错误的地方请指出,我会改进不要误导群众。
如果有需要探讨的加我QQ吧 1 2 2 1 3 8 2 9 9
...全文
6869 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_43869905 2019-09-17
  • 打赏
  • 举报
回复
nb.nb 说得真好 我都看不太懂
文盲老顾 2019-09-17
  • 打赏
  • 举报
回复
hookee 2019-09-17
  • 打赏
  • 举报
回复
qq_34028302 2019-09-16
  • 打赏
  • 举报
回复
https://download.csdn.net/download/qq_34028302/9437555 demo 下载
HQChart 2019-06-19
  • 打赏
  • 举报
回复
如果只是 下载和上传应该不需要, 在服务器上合并文件的吧, 下载还是根据上传的分块下载的。
y_w_x_k 2019-06-18
  • 打赏
  • 举报
回复
先留名,以后再看
于小九 2019-06-17
  • 打赏
  • 举报
回复
哈哈哈,超级大文件上传完成后台即使获得到md5的类楼楼可以分享一下学习学习吗
素材火 2017-09-29
  • 打赏
  • 举报
回复
刚写一个PHP断点上传DEMO,分享给大家:http://www.sucaihuo.com/php/3102.html
失散糖 2016-02-28
  • 打赏
  • 举报
回复
后台的文件为啥要合并呢,就弄一大堆文件碎片摆在那里如何
haoqingwang 2016-02-25
  • 打赏
  • 举报
回复
路过,但很受启发
line_us 2016-02-25
  • 打赏
  • 举报
回复
看看实现断点续传于秒传的具体要点
wyx3010218151 2016-02-24
  • 打赏
  • 举报
回复
引用 8 楼 dear_Alice_moon 的回复:
路过,长知识了。 今年年初时,因为我要下载一款由Sun公司研发的ISO镜像文件。下载好多次没有都出现断点续传问题,弄得我头疼的不得了。用迅雷下载不顶用,后得到高人指点自己在晚上找了一款国外的支持断点续传的工具。中间出现了3次断点中断,之后我又将其从断点处开始,终于将我想要的那份文件下载下来了。感觉棒棒哒,哈哈。
_明月 2016-02-24
  • 打赏
  • 举报
回复
路过,长知识了。 今年年初时,因为我要下载一款由Sun公司研发的ISO镜像文件。下载好多次没有都出现断点续传问题,弄得我头疼的不得了。用迅雷下载不顶用,后得到高人指点自己在晚上找了一款国外的支持断点续传的工具。中间出现了3次断点中断,之后我又将其从断点处开始,终于将我想要的那份文件下载下来了。感觉棒棒哒,哈哈。
zj198828 2016-02-24
  • 打赏
  • 举报
回复
不错
强好强 2016-02-24
  • 打赏
  • 举报
回复
雨网科技 2016-02-24
  • 打赏
  • 举报
回复
cattpon 2016-02-24
  • 打赏
  • 举报
回复
看看是什么~
blueink_200451 2016-02-24
  • 打赏
  • 举报
回复
路过学习了。涨了知识了。
业余草 2016-02-24
  • 打赏
  • 举报
回复
shiter 2016-02-24
  • 打赏
  • 举报
回复
之前只是知道是md5,但确实不知道是怎么做的

39,110

社区成员

发帖
与我相关
我的任务
社区描述
HTML5是构建Web内容的一种语言描述方式。HTML5是互联网的下一代标准,是构建以及呈现互联网内容的一种语言方式.被认为是互联网的核心技术之一。
社区管理员
  • HTML5社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧