文件上传哪家强

金轮好法王

最近的项目开发中,需要在网页应用中实现“文件上传”功能。

话说“文件上传”,是一个古老得不能再普通的问题,说简单也简单,但是要把它做到极致、完美,那就要考虑很多方面的问题,下面是我列举的几个功能及用户体验上的问题:

  • 是否支持一次选择多个文件
  • 是否支持添加文件夹
  • 是否支持文件拖曳、粘贴版复制
  • 是否支持暂停、恢复、取消上传
  • 是否支持断点续传
  • 是否有上传进度提示
  • 多平台、多浏览器支持问题
  • 服务端配合工作是否简单

本着 “90% 的问题,前人都已经有解决方案”的思路,加上我不想也暂时没有那个功力去“重复造轮子”,于是先上 Google 找“轮子”。

一钻进去,发现了另一片广阔的天地:得益于 HTML5 开发技术的流行,还真有不少做得很精致的文件上传库。

比如 jQuery File Upload 这个插件就可以轻松地实现方便灵活、用户友好的文件上传功能,它几乎完美地解决了跟文件上传相关的每一个问题。

下图是官方 Demo 的截图:

它强有多强

多文件支持

允许一次选择多个文件或文件夹。

拖放支持

可以从您的桌面或文件管理器中拖放他们在您的浏览器窗口中上传文件。

上传进度条

显示一个进度条显示为单独的文件和所有上传组合上传进度。

可取消上传

单个文件上传可以取消来停止上传进度。

可恢复上传

中止的上传可以与浏览器支持的 Blob API 进行恢复。

分块上传

大文件可以上传较小的块与浏览器支持的 Blob 的 API 。

客户端图像大小调整

图像可以自动调整大小,显示缩略图。

预览

支持对图像、音频和视频文件的实时预览和播放。

没有浏览器插件要求

该实现是基于开放的标准,如 HTML5 和 JavaScript 的,不需要额外的浏览器插件(例如 Adobe 的 Flash )。

跨站点的文件上传

支持上传文件到不同的域与跨站点的 XMLHttpRequest 或 iframe 重定向。

多个插件

允许在同一个网页上的使用多个插件实例。

可定制和可扩展

提供了一个 API 来设置各个选项,并定义回调方法的各种重载事件,能跟其他前端框架(比如 Angular)无缝衔接。

多重和文件内容流上传

文件可以被上传为标准的“多部分/窗体的数据”或文件内容流( HTTP PUT 文件上传)

完备的浏览器支持

支持的桌面浏览器:

  • Google Chrome
  • Apple Safari 4.0+
  • Mozilla Firefox 3.0+
  • Opera 11.0+
  • Microsoft Internet Explorer 6.0+

支持的手机浏览器:

  • Apple Safari on iOS 6.0+
  • Google Chrome on iOS 6.0+
  • Google Chrome on Android 4.0+
  • Default Browser on Android 2.3+
  • Opera Mobile 12.0+

兼容任何服务器端应用平台

适用于任何服务器端平台(PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) ,支持标准的 HTML 表单文件上传。

Tutorial

下载压缩包,解压到网站或者使用 npm、bower 等前端库管理工具就可打造跟官方 Demo 一样的客户端 + 服务端环境。

简单应用

网页上需要一个 input 元素:

1
<input id="fileupload" type="file" name="file[]" multiple>

需要加载的 js 文件有:

  • jquey-1.11.3.min.js
  • jquery-ui-widget.js
  • jquery.iframe-transport.js
  • jquery.fileupload.js

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>jQuery File Upload Example</title>
</head>
<body>
<input id="fileupload" type="file" name="files[]" data-url="server/php/" multiple>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="js/vendor/jquery.ui.widget.js"></script>
<script src="js/jquery.iframe-transport.js"></script>
<script src="js/jquery.fileupload.js"></script>
<script>
$(function () {
$('#fileupload').fileupload({
dataType: 'json',
done: function (e, data) {
$.each(data.result.files, function (index, file) {
$('<p/>').text(file.name).appendTo(document.body);
});
}
});
});
</script>
</body>
</html>

这样就实现了一个基础版的文件上传功能。

显示进度条

插件支持显示单个文件的上传进度 (progress) 显示和所有文件的总体上传进度(progressall) 显示:

1
2
3
4
5
6
7
8
9
$('#fileupload').fileupload({
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .bar').css(
'width',
progress + '%'
);
}
});

需要一个容器用来显示进度条:

1
2
3
<div id="progress">
<div class="bar" style="width: 0%;"></div>
</div>

给进度条显示不同颜色,可以通过 CSS 来设置:

1
2
3
4
.bar {
height: 18px;
background: green;
}

显示上传的文件名

你可以经常要将上传的文件显示到特定的元素上,这个可以通过 add 回调函数来实现:

1
2
3
4
5
6
7
8
9
10
$('#fileupload').fileupload({
dataType: 'json',
add: function (e, data) {
data.context = $('<p/>').text('Uploading...').appendTo(document.body);
data.submit();
},
done: function (e, data) {
data.context.text('Upload finished.');
}
});

点击开始上传

在上例基础上,可以通过按钮点击事件来触发上传(上例是自动上传)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$('#fileupload').fileupload({
dataType: 'json',
add: function (e, data) {
data.context = $('<button/>').text('Upload')
.appendTo(document.body)
.click(function () {
$(this).replaceWith($('<p/>').text('Uploading...'));
data.submit();
});
},
done: function (e, data) {
data.context.text('Upload finished.');
}
});

参考

彦祖老师 wechat