WEB 文件传输技术全讲解

导语

在WEB领域,文件上传,是一个古老的话题。对于不少网站而言,它是一个基础的功能。近些年以来,技术突飞猛进,唯独文件上传这一块却貌似依然停留在IE6的年代。对于用户来说,最不能忍受的事情,大概就是上传到99%的时候突然卡住不动然后被告知要从头开始了。因此断点续传一直是网页开发者们着力解决的技术难题。早期由于技术限制,在网页上实现断点续传的唯一途径是使用插件。直到HTML5出现以后,基于XMLHttpRequest2.0以及File API,断点续传问题才得以较好地解决。

WEB文件上传技术1.0

文件上传的最基本形式,是使用表单元素file:

<form enctype="multipart/form-data" action="upload.php" method="POST">
    <input name="userfile" type="file" />
    <input type="submit" value="Send File" />
</form>

这种方式最简单也最直接,而且所有浏览器都支持:

选择文件后,点击Send File按钮就可以上传文件了。然而这种方式缺点也是特别明显的,首先它是“同步”上传的,也就是说,点了上传按钮后,页面就处于锁定状态。而且如果页面报错,已填写的内容可能会丢失,文件也要重新上传。

WEB文件上传技术1.1

Form表单的上传是“同步”的,有没有办法像Ajax请求那样,不刷新页面也能提交文件呢?在HTML5出现以前,只能用iframe来做到这一点。方法是,生成一个iframe,里面的内容是一个表单,当我们点击上传的时候,触发该表单进行提交,并在upload.php中返回一段js进行回调处理即可。基于这个原理实现的组件,可以参考AjaxFileUpload

该方案很好地解决了Form表单同步提交方式的不少问题,但上传的过程中无法看到进度。用户可能会等得比较焦虑,有没有方法在上传的时候看到进度条呢?

WEB文件上传技术1.2

Flash曾经是网页世界里最闪亮的一颗星星。他除了播放多媒体以外,还提供了不少底层的文件操作接口。Flash8.0以后就开始提供FileReference类,例如使用brow可以打开文件选择器选择单个文件,browForMultifiles选择多个文件, upload开始上传, load把文件内容载入内存。通过这些方法,再结合ExternalInterface方法与页面的javascript进行交互,我们就可以做成一个基于Flash的文件上传组件,常见的组件有比如, Uploadify

从上面的分析来看,Flash不仅能在上传的时候显示进度,而且一次可以选择多个文件。由于它能把文件的内容载入内容,因此理论上可以实现断点续传。然而,这种一次性把整个文件全部载入内容的方式太占用系统资源,决定了它并不适合来对大文件进行断点续传。

此外,由于Flash已经逐步退出市场,基于它来实现文件上传的组件,可能无法在iOS、Mac等设备上使用。

WEB文件上传技术2.0

实际上,在早期除了上面说的三种技术外,还有用浏览器插件来实现文件上传的,例如早期的QQ邮箱超大附件。但浏览器插件的兼容性比较差,开发维护成本也高,所以也逐步退出。

HTML5标准提出以后,网页开发者可以不借助第三方技术,只用javascript就写出支持断点续传的上传方法。所谓断点续传,就是在上传文件的时候,每次向服务器发送一小片数据,当出现中断时可以跳过已发送的部分而续传。可以看出,断点续传的重要基础是分片。HTML5的File API提供了文件的分片操作,但传统的XMLHttpRequest不支持发送二进制数据,因此还需要利用HTML5的XMLHttpRequest2.0提供的API来发送已读的文件片段(这部分片段用FormData对象封装起来)。此外,如果要实现真正意义上的断点续传,也就是当页面刷新后对同一个文件续传,还需要在前端对文件进行识别,即sha1或者md5等技术。

可见,基于HTML5实现一个断点续传的功能,可以不依赖任何第三方插件。然而,当前的PC浏览器市场里,IE浏览器,特别是不支持HTML5的IE8依然占有相当高的份额。对于这部分浏览器用户,我们不得不继续沿用FLASH来兼容。

总的来说,一个好的上传组件,除了要支持断点续传,能提供上传进度显示,支持文件多选等操作,还要兼容各种常见的浏览器,保证基本的上传功能可用。本文所介绍的上传组件——Pan Upload,基于开源组件plupload改造而成。除了支持基本的断点续传,还支持文件SHA1识别(即支持秒传、刷新页面后续传),并提供了丰富的API来支持上传进度显示,支持多文件与文件目录上传,并可以自定义文件格式过滤。对于现代浏览器,它自动启用HTML5的特性,完成快速的断点续传;对于老式的IE浏览器,它自动切换到FLASH上传方式,提供基本的上传功能。

Pan Upload的功能截图:

该组件的使用比较简单,除了传统的<script>标签引入之外,它还支持AMD方式引入,引入方法:

<script type="text/javascript" src="http://file.gad.qq.com/js/plupload.full.min.js"></script>

或者使用requirejs引入:

require(['jquery', 'http://gad.qpic.cn/assets/js/file/plupload.full.min.js?require_js=1'], function($) {
    $("#test_fileload").pan_upload_raw({
           max_file_count: 1,  //最多上传的文件数量
           multi_selection: false, //是否支持同时传多个文件
           flash_swf_url: '/assets/js/Moxie.swf', //flash地址,适配IE
           filters: {max_file_size: '10mb', mime_types: [{title: "图片", extensions: "jpg,png,gif,tif,webp"}]},  //文件大小选择与格式过滤
           events: {
                FilesAdded: function(up, files) {
                    //文件添加的回调
                }, UploadProgress: function(up, file) {
                    view.upload.percent = file.percent;
                    //文件上传进度回调
                },
                FileUploaded: function(up, file, info) {
                    //文件上传完毕回调
                    try {
                        up.disableBrowse(false);
                        view.upload.uploading = false;
                        var data = JSON.parse(info.response);
                        if (!data.success) {
                            popup.showPopup('warn','提示',"上传失败");
                        } else {
                            view.archive.cover = data.image_url;
                        }
                    } catch (e) {
                        popup.showPopup('warn','提示',"上传失败");
                    }
                },
                Error: function(up, error) {
                     //错误处理
                     popup.showPopup('warn','提示',error.message);
                }
            }
        });
});

这就完成了前端组件的引入。然而,断点续传的实现,离不开后台的支持,Pan Upload组件除了提供前台的完整支持外,在后端还提供了配套的服务:

  1. 后台支持续传、重传、秒传;
  2. 文件格式识别与处理:图片文件自动转存到CDN并提供尺寸变化(缩略图)、鉴黄、水印等服务;音视频文件自动转码并转存到CDN,提供多种画质的在线点播服务;PPT/WORD文件自动解析并提供在线预览服务等;
  3. 下载链接防盗链;
  4. 用户存储空间管理,垃圾文件定期自动回收管理等

有关后台架构的介绍,将会在另外一篇文章专门介绍。

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

潘兴颂的专栏

1 篇文章1 人订阅

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏落影的专栏

真机的代码覆盖率测试

代码覆盖率测试 以前虽然写过单元测试,但很少监测测试的完整程度,测试用例也经常存在重复的情况。这次在测试的要求下开始接入代码覆盖率测试。什么是代码覆盖率?就是测...

3625
来自专栏知识分享

一,ESP8266下载和刷固件(基于Lua脚本语言)

用自己的小板测试...... 安排上呢 一, ESP8266下载和刷固件(Lua开发----体验一下lua开发的魅力所在) 二, 控制一个灯亮灭 三, TCP服...

2967
来自专栏phodal

【工具推荐】价值百百万的后台微服务生成工具

上周参加公司的一个微服务 WorkShop,期间使用到了这么一个强大的工具。 在 Workshop 里,我们所要做的就是做一个类似于下图的应用,由多个服务 + ...

1745
来自专栏Jerry的SAP技术分享

如何将SAP Multi Target应用部署到SAP云平台的Cloud Foundry环境去

SHINA是SAP HANA Interactive Education的缩写,是一个demo应用,用于演示如何开发SAP HANA原生应用。

3787
来自专栏华章科技

全栈工程师的18项基本技能,你会多少

本文总结了正在撰写的《Growth:Web开发思想》里提出的一系列实践,为18个步骤。

471
来自专栏SAP最佳业务实践

SAP最佳业务实践:FI–自建资产(资本投资订单)(164)-8 KO04投资订单的最终结算

4.10 KO04完成订单 本步骤中订单将被关闭。 投资订单最终结算已完成,余额为零。 角色:资产会计 会计核算 -控制 -内部订单-主数据 -订单管理员 1....

2956
来自专栏知识分享

5-51单片机WIFI学习(学会刷固件)

上一篇链接  http://www.cnblogs.com/yangfengwu/p/8757036.html 写这篇文章之前我一直在想是直接进入主题开始AT指...

3055
来自专栏性能与架构

nginx实例 - 如何防止大图片占满带宽?

场景 前几天网站出现了访问缓慢的情况,查看系统资源状况后,发现出网带宽一直是占满的状态 查看服务器日志,发现了很多10M左右的超大图片的请求,这些图片占满了...

3806
来自专栏TSW

让产品改host你的良心不会痛吗!!!!

1153
来自专栏林德熙的博客

win10 uwp 判断设备类型

本文提供一个方法,可以判断当前的设备是PC还是手机,UWP 判断当前的 PC 是否平板模式,判断是否苏非的设备

441

扫码关注云+社区