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

 

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

首先我们分析一下要实现断点续传于秒传的具体要点。

 

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,其他运算都分摊到每一碎片上了。

 

 

 

  上面的东西没有经过大小项目验证全是理论上的,也许我是错的。我说的都是我自己理解的有错误的地方请指出,我会改进不要误导群众。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值