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 条评论
登录 后参与评论

相关文章

来自专栏Web 开发

NodeJS那些事

下半年做了挺多活动型需求,因为我们业务人力有限,我在业务的策略是不依赖NodeJS。

1850
来自专栏张戈的专栏

解决IE响应式的解决方案css3-mediaqueries.js不生效问题

前阵子解决了博客在低版本 IE 下会假死的问题,发现居然是因为我自定义 CSS 的闭合误用了中文大括号导致的! 解决这个问题之后,又发现了另外一个坑:发现博客在...

4189
来自专栏24K纯开源

Android Studio快捷键每日一练(3)

23、启停用断点 苹果:Cmd+F8    Windows:Ctrl+F8 接下来的几个功能都和调试相关。我们就从一个最基本的功能开始:添加一个断点。相信到目前...

2336
来自专栏Django中文社区

评论

创建评论应用 相对来说,评论其实是另外一个比较独立的功能。Django 提倡,如果功能相对比较独立的话,最好是创建一个应用,把相应的功能代码写到这个应用里。我们...

6146
来自专栏社区的朋友们

爬虫实战 : 爬虫之 web 自动化终极杀手(下)

最近写了好几个简单的爬虫,踩了好几个深坑,在这里总结一下,给大家在编写爬虫时候能给点思路。本次爬虫内容有:静态页面的爬取。动态页面的爬取。web 自动化终极爬虫...

1.7K1
来自专栏FreeBuf

JIS-CTF靶机+Kioptrix靶机渗透

最近一直在down各种CTF靶机玩,本次分享的2个靶机因较基础,故合并成一篇文章发表,本文章仅为初学者练手学习使用,大神们勿喷,感谢各位大佬!

1554
来自专栏知晓程序

开发者自述:我如何用云函数快速搞定「模板消息推送功能」

1922
来自专栏NetCore

不错的node.js入门

关于 本书致力于教会你如何用Node.js来开发应用,过程中会传授你所有所需的“高级”JavaScript知识。本书绝不是一本“Hello World”的教程。...

4598
来自专栏技术栈大杂烩

Python: mutilprocessing Processing 父子进程共享文件对象问题

multiprocessing python多进程模块, 于是, Processing也是多进程的宠儿. 但今天讨论的问题, 似乎也能引起我们一番重视

1656
来自专栏非著名程序员

Android Studio详细安装流程和配置、主题

? 原文作者:欧神. 杨 / OCN Yang 原文地址:http://ocnyang.com/2016/09/13/AndroidStudioSet/ 特别...

2596

扫码关注云+社区

领取腾讯云代金券