这篇文章发布于 2013年11月5日,星期二,02:22,归类于 JS实例。 阅读 257492 次, 今日 23 次 63 条评论
by zhangxinxu from https://www.zhangxinxu.com
本文地址:https://www.zhangxinxu.com/wordpress/?p=3754
一、网盘割据的时代
不知大家有没有观察过,在秋季,也就是眼下这个时间,当阵风挂起的时候,地上的落叶就会以一个接一个,翻滚着一同被吹走,这就是“跟风”。老祖宗确实很有智慧,造出来的词语源于生活,又高于生活。
眼下,又是另一波跟风之势——“网盘”,犹如当年团购一样。不过,网盘还是有一定的技术和其他成本,因此,还不像团购那样“落叶漫天飞舞”的状态。但是,各大公司相继介入,可谓又是另外一场群雄之战。
我并不是专业的产品人,也不是公司的决策者,因此,面对一些纷杂繁芜的现象,自己无心去深入,也不会去评价。立志做个技术人,因此,我所关心的可能就是技术实现,至于孰对孰错,恩怨情仇,公关伎俩,生死天命等一概作云烟从眼前飘过。
网盘中有个很重要的,可以说是核心的功能,就是文件上传,So,本文就来说说这个上传,如何在HTTP协议下实现文件的断点续传呢?
二、文件断点续传的实现
目前从实用技术角度讲,文件上传的断点续传实现主要是借助客户端,例如,我们首次进入微云,会看到下图所示的“控件安装”提示:
百度网盘似乎有文件上传暂停的功能,这似乎是借助swfUpload实现的。
也就是,这些带续传功能的上传都不是使用HTTP协议实现的,也就是不是传统的网页技术(HTML+CSS+JS)实现的。
然,times are changing, 事物发展,时代变化。以前的一些所谓的“不能”、“不可能”都将成为过去。
上月一篇独苗文章介绍了XMLHttpRequest level 2(下简称Ajax 2.0)中的一些支持的数据格式,如果稍微关注,应该知道,Ajax 2.0中最大的变化之一就是对二进制数据的支持,而且提供了一个可以直接处理二进制数据的方法——slice
方法。
JS中的字符串有slice
方法,数组也有。Ajax 2.0经过一些变化后,现在也和数组、字符串的slice
方法语法完全一致了。于是,我们就可以把二进制数据流想象成一些连续的字符串数据,并对这些二进制数据进行slice
处理。
比方说怎样的场合呢?
PHP默认似乎有个最大文件上传的限制 – post_max_size
,我的本地看了下,是64M
.
此时,我们想一次性传一个80M
的动作片精华片段,就会以失败告终。
但是,有了slice
方法,我们可以把文件分割,比方说,每20M
作为一个请求发送出去,后台再把这些二进制数据拼合成一个完整文件。
slice(0, 20); slice(20, 40); slice(40, 60); slice(60)
还有一个很重要的场合就是断点续传!
文件传输是个具有时间周期的过程,从玩三国杀的离线率可以看出,掉线什么的是常有的事情。显然,传文件必定会存在传着传着就死在99%位置的情况。
你想啊,大鼻孔姐的片子想放到网盘里,随时随地可以欣赏。结果看着进度条等了40分钟,好不容易传到99%,突然断电…………开机后,发现又要重传,是不是小弟弟要气得短小软?显然,后果很严重哈~
因此,对于大文件而言,断电续传功能很重要。有了Blob数据格式的slice
方法,一切都变得简单了。
我的思路是这样的,有两条:
1. 浏览器记住(如localStorage)最近一次成功传输的位置;当再次上传这个图片的时候,直接从浏览器存储的位置开始传。
2. 浏览器不做任何事情,在上传之前先去后台走一遍,看看目前此文件是否存在,以及存在的大小,返回给浏览器,然后浏览器再决定上传的起始位置。
理性的分析以及实践的结果表明,第二种思路可行性更高。//zxx: 并不一定是最好的思路,您可以自己想出更精彩的实践方法
如果用文字举例的话就是:
某老师的视频是80*1024*1024
B, 我们每次传1024*1024
B,也就是1M
,假设传了79M
了,结果大脚一抖,电源关掉有木有!某老师就这样随风逝去了……
用户重新开机,决定再次传这个80M的视频。当用户选择了这个文件后,我们先去后台走一圈,把当前已经传好的文件大小反馈给客户端(Ajax 1.0就可以),JS拿反馈大小和源文件大小一比对,奶奶的,残缺啊!于是,就从残缺位置slice
,这里就是:
file.slice(79*1024*1024)
接着之前的只传了1M就OK啦!于是,断点续传实现。
由于网页本身的局限性,我们没法直接触发本地文件的上传。因此,目前而言,断点文件还是要用户选择(相比客户端上传软件多了这一步)。
三、文件断点续传的实践
您可以狠狠地点击这里:HTTP协议下Ajax实现的文件断点续传demo
说明:
- 上demo可以说是一个比较完善的上传体验,有删除,重传,续传,进度条等常用功能。
- 基于Ajax 2.0的二进制文件传输实现,因此,IE10+,Chrome以及Firefox等浏览器支持。另外JS原生,无外部依赖。
- 空间的流量月月吃紧,经常溢出不够用,因此,为了节约成本,只允许最大
200K
的文件。所以,大家想要测试断点续传效果,可以通过工具,把自己的浏览器速度限制到10~20K
每秒。 - demo页面每
100K
就会对文件进行一次分割上传,因此,100~200K
大小文件会有看到2次上传请求。PS:实际开发时候,应该至少1M
一次分割。 - 为了直观表现断点上传的功能,我会截一个本地的视频给大家演示,并原声重现。
- 后台PHP很简单,就是追加二进制数据,
file_put_contents
方法有个FILE_APPEND
选项,直接追加,很好用的! - 正好研究了下开源协议,这里请容我练个:demo页面中的JS+CSS+HTML源代码遵循GPL协议,即您可以任意复制,修改,但是,只能作为学习或私人项目使用,不能作为商业软件的一部分去出售。如有疑问,可zhangxinxu@zhangxinxu.com联系。
其他一些技术细节,懂的人不说也知道是怎么回事,不懂的人要花很大功夫斟酌表达才可以。然,目前时机不成熟,付出收益比略低,因此,这里不具体叙述,有问题欢迎邮箱联系。
add on 2016-04-13
目前线上demo貌似文件都无法上传成功,感觉可能和服务商的服务器设置有关,安全限制还是什么的,我也没深究,我本地是好的,可以秒传。大家不要太在意这个细节。
add on 2017-09-19
今天偶然看到服务商有个设置,我开启了下,嘿,可以上传了。
add on 2018-11-11
截止到今天,已经有不下于3人索要源码,都是5块钱成交的,含JS源码和PHP代码。如果你也有意向,欢迎邮箱联系(iamzhangxinxu@qq.com),邮件内容为求源码,愿意支付就可以了。
add on 2020-03-30
求源码的好多人,也愿意付费,但是每次我都要一个一个邮件回复,折腾的时间算下来成本远远不止5块钱,所以决定了,走诚信支付形式,想要源码自己下面地址下载然后支付即可。
源码在下面:
链接:https://share.weiyun.com/5apGYTk 密码:2p3mrm
支付这里:
下面视频演示下断点续传的效果:
因为半夜三更录的视频,老婆大人已经安然就寝,所以自己声音比较小,发音也不太准,貌似被优酷搞糊了,大家凑合看看吧~~
四、说点题外话
上月本人只更新了一篇文章。有一周是整周的培训。然后除了研究现在这个Ajax断点续传,还在做一个自己的开源项目(已经用了两周了,本周应该可以结束)。
本人最近有在纠结专利与开源的事情。我司申请专利很是方便,而且公司鼓励,且对个人发展有很有帮助,我显然是要积极做这些事情的。但是,个人价值观中很重要的一点就是要留下什么,因此,自己是非常喜欢共享东西的。于是就存在一个矛盾,有些东西,例如一些创新的想法或者实现方式,如果成为的专利,就不好拿出来随意分享了,因为,自己申请的专利不是自己的而是公司的,自己完全没有把控权。头疼~~
不过,今天例会跟组里前辈沟通了下,算是想通了。这样子,自己平时业余时间研究的东西,即使很赞,很具有专利性,我也会及时和大家一起探讨与进步;如果是实际工作发现的创新性想法,则走专利路线,技术封闭。我举得这样的权衡应该是很不错的,不知大家的看法如何呢?
哈哈,今天特地研究了下开源版权的问题,学到了不少,各种License都大致了解了一点,文中好像就有体现了,
博客所有技术文章遵循CC协议,即署名、非商业性使用、相同方式共享、禁止演绎。
一些开源插件等遵循其他协议,回头补上~~
本文为原创文章,转载请注明来自张鑫旭-鑫空间-鑫生活[https://www.zhangxinxu.com]
本文地址:https://www.zhangxinxu.com/wordpress/?p=3754
(本篇完)
- 学习了,CSS中内联SVG图片有比Base64更好的形式 (0.302)
- 一言难尽的registerProtocolHandler()方法 (0.302)
- HTML5 file API加canvas实现图片前端JS压缩并上传 (0.295)
- HTML input type=file文件选择表单元素二三事 (0.252)
- 理解DOMString、Document、FormData、Blob、File、ArrayBuffer数据类型 (0.204)
- Ajax Upload多文件上传插件翻译及中文演示 (0.191)
- CORS ajax跨域请求php简单完整案例一则 (0.141)
- 使用AbortController abort中断原生fetch或axios请求 (0.141)
- 小tips: 纯前端JS读取与解析本地文本类文件 (0.104)
- 纯前端实现可传图可字幕台词定制的GIF表情生成器 (0.104)
- ajax与HTML5 history pushState/replaceState实例 (RANDOM - 0.040)
www-html5upload-com
1)支持断点续传
2)支持直接拖拉文件到浏览器中,更新上传队列
3)支持上传文件夹,并保持目录结构
4)服务器端以文件的md5值作为文件名存储文件
5)支持与服务器端文件进行完整文件md5校验
6)支持跨域上传
7)客户端无需安装任何插件,HTML5upload以jQuery插件形式进行调用
8)适用于任何服务器端平台(PHP,c#, Python, Ruby on Rails, Java, Node.js, 等…)
9)阿里云版,支持Web直传oss
10)Electron版,支持保持未上传完成对文件队列。