文档章节

WebUploader 文件上传优化总结

kisshua
 kisshua
发布于 2016/06/27 22:38
字数 3618
阅读 1290
收藏 12
点赞 0
评论 0

 

HTML VS FLASH

对于文件上传,相信还有不少同学还停留在FLASH时代,其实现在 HTML5 不仅可以实现文件上传,而且可以做得更好。

以下是对 HTML5 与 FLASH 就文件上传方面的功能调研测试得出的结果。

功能描述 FLASH HTML5
文件多选
格式过滤
拖拽(文件 & 文件夹)
截屏粘贴
Cookie & Session
文件内容读取 ✓ 快150%
图片预览&裁剪 ✓ 快200%
文件上传 ✓ 快10%
进度跟踪 ✓ 更加精准

PS: 截屏粘贴是指,如果剪切板里面存在图片数据,是可以通过 CTRL + V 将此图片作为文件添加到文件上传组件中的。让剪切板中有图片数据有很多方式:截屏软件(如QQ截屏),浏览器中右击图片点击复制,QQ聊天软件中复制图片...

可以看出,采用 HTML5 技术与传统的 FLASH 技术相比,能实现的功能更多且性能优势特别明显。

更多调研细节请移步到 这里

虽然 HTML5 优势非常明显,但是如果目前支持 HTML5 的浏览器占比情况不理想,采用 HTML5 技术的文件上传还是不能带来足够的收益!

让我们先来看看由 TNW 提供的2014年3月份全球浏览器占比图。

通过浏览器占比可以推算出,目前支持 HTML5 的浏览器占比高达64.5%,加上 HTML5 有如此大的优势,看来完全没有理由拒绝采用 HTML5 来实现文件上传了。

但是还有35%的浏览器不支持 HTML5,怎么办?

为了考虑最大的兼容性,目前 WebUploader同时实现了 HTML5 和 FLASH 两套运行时,在不支持 HTML5 的浏览器里面自动切换成 FLASH 方式上传,这样的好处是,既能在条件允许的情况保证 HTML5 发挥出其高效的优势,又能在不支持 HTML5 的浏览器里面保证能正常运行。

如何优化文件上传性能?

对于文件上传性能优化,可以从两个方面来着手,即上传前的优化和上传过程中的优化。

上传前的优化

主要有两个思路。

  • 思路一:通过减少文件体积,减少上传流量来优化。
  • 思路二:通过合并小文件,减少请求数来优化。

基于这两个思路,我们尝试了以下几种方案。

  • 图片压缩

    如果上传的是图片类文件,存在一部分用户喜欢直接选择相机或者手机拍摄的原始文件进行上传,对于这类图片,图片的分辨极高,高达5000多。这就注定了此图片的文件体积不会太小。其实如果只是在电脑上查看,1千多的分辨率就已经足够。于是我们尝试通过js将此类图片进行缩小,得出的结果是:1张(5184×3456)大小为5M的jpg图片,缩小到(1600x1600)后,体积变成了407kb, 直接节省了4.5M的流量。

  • ZIP 合并小文件

    类似于拷贝文件夹到U盘,如果小文件比较多,拷贝过程非常慢,通常我们的做法是将文件夹打包成一个文件再拷贝,速度往往要快出许多。其实文件上传也一样,如果能把体积比较小的文件合并成一个文件,请求数就会少了很多,这样是不是就提高了整体文件上传速度呢?

    但是,通过测试得出的结果是不尽如意的。ZIP的运算效率太低,以至于只有在2G网络下才有速度提升,3G和wifi网络下反而变慢了。更多细节请移步到 这里

  • SPRITE 合并小图片

    类似于css sprite, 将多个小图片画到一张大图片上,通过这种方式来进行合并,思路和zip合并差不多,但是采用的技术不太一样,此方案是直接用canvas来画,经过测试发现速度比zip快出来10倍,总体能带来20%左右的速度提升。

    但是此方案只满足于图片类文件,且服务端需要通过位置信息还原出小文件,带来一定的服务端开发成本,目前并没有采用此方案。更多细节请移步到 这里

  • 直接合并文件内容

    其实,并不需要采用ZIP或者SPRIT方式合并文件,把文件读取出 arraybuffer 后是直接可以连接在一起的,之后还可以再次转成 blob 发送到服务端,或者直接发送 arraybuffer,理论上性能应该比SPRITE方案靠谱。

    但是这块没有进行详细的调研,在此就不多说了。

上传过程中优化

主要采用并发与分块,以下将细说这两个方案。

并发上传

采用此方案主要是源于单一请求无法让网络达到饱和,于是我们来尝试采用并发方式看能否提高总体文件上传速度。

以下是通过测试20个1M的文件在不同的并发数下得到的总体上传时间对比图。

并发对比图

很明显,并发数越多速度越快!

但是,并发数越多,给服务端带来的压力也越大,如何去选择一个合适的并发数呢?

主要可以从三方面去考虑。

  1. 并发数越多,服务端压力越大,所以选择并发数不能太大!
  2. 同时每个浏览器都有固定的最大并发数限制,所以选择并发数不能超出这个值。
  3. 从上面的图标可以看出,并发数到了3以后,收益开始渐渐不明显。

如是,最佳的并发数应该是3。

PS: 以下是常用浏览器的最大并发数信息。根据这个表可以说明为什么前面的测试结果,并发数只测试到了6,原因是chrome的最大并发数是6,当并发设置到7的时候,第7个请求是处于等待状态,直到前面某个请求完成,才会开始有进度。

浏览器 HTTP 1.1 HTTP 1.0
IE 6, 7 2 4
IE 8 6 6
Firefox2 2 8
Firefox3 6 6
Safari 3, 4 4 4
Chrome 1, 2 6 ?
Chrome 3 4 4
Chrome 4+ 6 ?

为什么并发会更快?

这里列出了我个人觉得可能的原因。

  • 多请求能抢占更多的带宽。
  • 服务器端可能针对单一请求限速。
  • 跨域时,并发可以共用options验证请求,浏览器有个特点是,对于跨域请求,如果在一定的时间内,有多个请求,只会发送一个options请求验证的。

    options请求共用

    左边是非并发的情况,右边为采用并发的情况。可以看出,当不采用并发的时候,每个文件上传请求前都会进行options请求验证,而并发的时候,三个文件上传请求共用了一个opions请求。

分块上传

为什么要采用分块上传?

试想一下,如果上传的文件是一个大文件,本来上传时间就相对较久,再加上网络不稳定各种因素影响,容易导致传输中断,用户除了重传 整个文件外没有更好的选择。采用分片上传可以很好地解决这个问题。

什么是分片上传?

分块上传,就是把一个大的文件分成若干块,一块一块的传输。如上面的case, 如果传输中断,仅需重传出错的分片,而不需要重传整个文件,大大减少了重传开销。

那么,采用分块上传还有哪些优势?

  • 更强容错能力

    如以上的case, 出错重传,仅需重传一小块。

  • 可以模拟暂停与继续

    对于一个http请求,其实并没有暂停功能,要不就是已完成,要不就是已中断。如果不分块,是没法做暂停功能。但是如果采用分块上传,在某个分块上传完了后不自动开始下个分块上传,是不是就实现了暂停功能?

    利用此功能,就可以通过网络检测,在网络断开的时候自动暂停传输,网络恢复后,继续传输,给用户带来更好的体验效果。

  • 利用并发提速

    如果单独的上传一个大文件,只有采用了分块上传才能利用并发请求来提速。

  • 更精准的速度跟踪

    关于客户端监控上传进度,其实监控的都是客户端的发送速度,服务端有没有接收,有没有存储,是不知道的,只有在整个请求完毕,收到服务端反馈后才能确定数据已经成功接收。这样也就解释了进度显示的时候,长长出现,进度条瞬间到100%,要过一段时间才全部完成。如果采用分块上传,每个分块上传完成,可以确定这个分块服务端已经成功接收。

当然,分块也会有一定的副作用,本来是一个请求,分块后变成了多个请求,自然会带来网络开销。那么具体是个什么的情况呢?

以下是通过测试3个30M的文件在3个并发下调整不同的分片大小得出的总体时间消耗表。

分块对比图

可以看出来,分块越小,时间消耗越大,尤其是分块大小小到256K的时候,时间花费增长特别明显。

那么,如何选择一个合适的分块大小?

主要有三个方面的考虑。

  • 分块越小,请求越多,开销越大。所以不能设置得太小。
  • 分块越大,灵活度越小,前面所说的那些优势就会相对越不明显。故不能太小。
  • 服务端一般都会有个固定大小的接受buffer(client bodybuffer_size), 分块的大小最好是这个值的整数倍。

综合这些考虑,推荐的分块大小是2M-5M,具体size根据产品中文件上传的大小分布来定。如果上传的文件大部分是500M以上,很大的文件,建议是5M, 如果相对较小,推荐2M。

断点续传

有了分块上传,其实我们可以实现更多的功能。试想,如果服务端能够把每个已成功上传的分块都记住,客户端可以快速验证,条件选择跳过某个分块,是不是就实现了断点续传?

那么,断点续传能带来哪些好处?

  1. 节省流量,避免上传重复的分块。
  2. 减少用户等待时间。
  3. 可恢复的上传。出现中断,就算浏览器刷新或者是换了台电脑也能恢复到上次中断的位置。

那么现在最关键的问题是如何标识一个分块了。怎样标识让服务端好入库,同时客户端可以快速的计算出来与服务端验证,换句话说就是,如何去找出分块的唯一ID。

之前尝试过文件名+分块编号,或者再加文件大小,文件最后修改时间什么的,都无法保证分块的唯一性。于是还是直接采用 MD5 的方式来序列化文件内容吧,这样就算是文件不同名,只要内容是一致的也会正确地识别出是同一个分块。

那么现在的逻辑就是,每次分块上传前,根据内容 MD5 序列化,得到一个唯一ID,与服务端验证,如果此分块已经存在于服务端,则直接跳过此分块上传,否则上传此分块,成功后,服务端记下此分块ID。

如是,分块上传是不是具有了秒传的功能?既然分块能秒传,那么整个文件是否也可以秒传?

秒传

分块能秒传,整个文件当然也能秒传,关键还是看 MD5 的性能。

md5性能

通过以上测试结果可以看出,如果文件大小在 10M 以内,是可以真正的秒级内完成的,大于这个值时间花费就大于1秒了,比如一个200M的文件 MD5 时间花费需要13秒左右。

但是,即便如此,相比于文件传输时间花费,MD5 的时间花费根本就不算什么。对于类似于百度云,文库这类的产品,在上传一个文件的时候很可能服务端已经存在了此文件,如果多等个几秒钟,能跳过整个文件上传,我觉得是非常划算的。

另外,如果是一次上传多个文件是可以在算法上去优化这个过程的。

  • 验证过程提前到当前文件的传输期

    如果当前文件已经在传输了,这个时候,用户是处于等待状态,机器也处于等待期,如果把下一个文件的验证过程移至此过程,那么用户的等待 MD5 的时间和等待当前文件传输完成的时间就重合了。这样用户就只需要等待第一个文件的验证过程。

  • 小文件优先处理,减少用户等待时间

    因为第一个文件的验证等待无法避免,如果第一个文件处理的文件越小,是不是等待的时间就越短?所以把队列中最小的一个文件放到第一个优先处理可以进一步减少用户等待时间

  • 更换序列化算法,取段MD5

    其实对于某些二进制文件,如JPEG,前面一段数据记录了很多此图片的信息,比如:拍摄时间,相机名称,图片尺寸,图片旋转度等等,直接 MD5 这一段数据基本上就可以保证此文件的唯一性了。只要取段的总大小小于10M,再大的文件也能在1秒内完成序列号工作。

 

本文转载自:http://itindex.net/detail/49267-webuploader-文件-上传

共有 人打赏支持
kisshua
粉丝 30
博文 138
码字总数 33773
作品 0
武汉
后端工程师
spring-web-4.3跨域@CrossOrigin详解

说明:项目前后端分离会用到跨域访问。 springmvc4.3.4跨域访问通过注解@CrossOrigin(origins = "*")开启,此注解可应用于类或者方法上。 经过测试WebUploader 0.1.5跨域上传这样设置是可行的...

小涴熊 ⋅ 06/21 ⋅ 0

webuploader java版本

网上一些webuploader上传的资料,有php版和java版本的,做了一下整合,现分享以下成果,可以讨论,不喜勿碰。说一下过程。 第一步:下载地址,提供官网地址 http://fex.baidu.com/webupload...

卯金刀GG ⋅ 2016/12/20 ⋅ 0

谈一谈大文件上传——前台分片和后台合并

欢迎光临我的博客拓跋的前端客栈,这个是原文地址。如果您发现我文章中存在错误,请尽情向我吐槽,大家一起学习一起进步φ(>ω<*) 最近做了一个需求,需要上传镜像的tar包,小的3、5G,大的可...

zhleven ⋅ 01/04 ⋅ 0

使用webuploader时报错: Uncaught Error: jQuery or Zepto not found!

使用webuploader时报错:Uncaught Error: jQuery or Zepto not found! 请教大神这要怎么解决?我的代码如下,直接用的官网Getting Started的代码。...

我是程序yuan ⋅ 2017/09/18 ⋅ 0

webuploader的使用

WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。在现代的浏览器里面能充分发挥HTML5的优势,同时又 不摒弃主流IE浏览器,沿用原来的FLASH...

大叔做web前端 ⋅ 2014/11/28 ⋅ 4

webuploader解决不能重复上传同一个文件的问题

webuploader选择文件A上传,再选择文件B上传,接着再次选择文件A,就不能再上传了,下面给出解决代码

zchuanzhao ⋅ 2016/10/12 ⋅ 0

WebUploader的缩略图如何在后台保存以及下次打开页面时如何展示的问题

大家好,我的使用场景如下:(我觉得比较通用) 用户在需要专家帮忙的时候需要填写文字信息以及上传图片 可上传多图,每选择一个图片无需点击“上传”按钮而自动上传 上传成功后,出现缩略图...

错觉 ⋅ 2015/12/09 ⋅ 6

大神们,谷歌浏览器53为什么点击上传图片要等很久

我用webuploader上传图片,以前谷歌浏览器版本没升级之前,一切正常。现在谷歌升级之后,点击上传按钮要等很久才弹出文件选择的弹窗。 其次,我用其他的浏览器,如火狐、IE、遨游等等,均没有...

漠沙 ⋅ 2016/10/26 ⋅ 2

Kodexplorer 2.0 版即将全新问世

新版本增加了多用户以及权限管理。 极大优化了文件上传,文件、文件夹拖拽上传。 详情如下; ##fix bug:(bug解决和程序优化) 优化文件打开处理 文件&文件夹:含有%、+号的处理(显示不出等问...

雾渺 ⋅ 2014/03/10 ⋅ 0

使用Web Uploader实现多文件上传

引入资源 使用Web Uploader文件上传需要引入三种资源:JS, CSS, SWF。 <!--引入CSS--> <link rel="stylesheet" type="text/css" href="webuploader文件夹/webuploader.css"> <!--引入JS--> <......

DavidBao ⋅ 2015/04/15 ⋅ 7

没有更多内容

加载失败,请刷新页面

加载更多

下一页

istio 文档

https://istio.io/docs/concepts/ https://istio.io/docs/concepts/traffic-management/handling-failures/ https://istio.io/docs/concepts/traffic-management/rules-configuration/......

xiaomin0322 ⋅ 9分钟前 ⋅ 0

编程语言的作用及与操作系统和硬件的关系

一、编程语言的作用及与操作系统和硬件的关系 作用:编程语言是计算机语言,是一种程序员与计算机之间沟通的介质,通过编程语言可以使得计算机能够根据人的指令一步一步去工作,完成某种特定...

slagga ⋅ 20分钟前 ⋅ 0

runtime实现按钮点击事件

也不能说是实现吧,,,就是有点类似于RAC里边的写法,不用给btn添加另外的点击事件,就那个add...select...这样子很不友好,来看下代码: [self.btn handleControlEvent:UIControlEventTou...

RainOrz ⋅ 20分钟前 ⋅ 0

Windows系统运维转linux系统运维的经历

开篇之前,首先介绍一下我的背景把:我是一个三线城市的甲方运维。最近,在《Linux就该这么学》书籍的影响下和朋友小A(Linux运维已经三年了,工资也比我的高很多)的影响下,决定转行。最近...

linux-tao ⋅ 21分钟前 ⋅ 0

zip压缩工具,tar打包工具

zip压缩工具 zip打包工具跟前面说到的gzip,bz2,xz 工具最大的不一样是zip可以压缩目录。如果没有安装,需要使用yum install -y zip 来安装。安装完之后就可以直接使用了,跟之前提到的压缩...

李超小牛子 ⋅ 29分钟前 ⋅ 0

使用npm发布自己的npm组件包

一、注册npm账号 官网:https://www.npmjs.com/signup 注册之后需要进行邮箱验证,否则后面进行组件包发布时候会提示403错误,让进行邮箱核准。 二、本地新建一个文件夹,cd进入后使用npm i...

灰白发 ⋅ 31分钟前 ⋅ 0

010. 深入JVM学习—垃圾收集策略概览

1. 新生代可用GC策略 1. 串行GC(Serial Copying) 算法:复制(Copying)清理算法; 操作步骤: 扫描年轻代中所有存活的对象; 使用Minor GC进行垃圾回收,同时将存活对象保存到“S0”或“S...

影狼 ⋅ 31分钟前 ⋅ 0

JVM性能调优实践——JVM篇

在遇到实际性能问题时,除了关注系统性能指标。还要结合应用程序的系统的日志、堆栈信息、GClog、threaddump等数据进行问题分析和定位。关于性能指标分析可以参考前一篇JVM性能调优实践——性...

Java小铺 ⋅ 32分钟前 ⋅ 0

误关了gitlab sign-in 功能的恢复记录

本想关sign-up的,误点了sign-in 退出后登录界面提示: No authentication methods configured 一脸懵逼.. 百度后众多方案说修改application_settings 的 signin_enabled字段; 实际上新版本字段...

铂金蛋蛋 ⋅ 33分钟前 ⋅ 0

登录后,后续请求接口没有带登录cookie可能原因

1.XMLHttpRequest.withCredentials没设置好,参考https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/withCredentials...

LM_Mike ⋅ 33分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部