jQuery用FormData实现文件上传的方法


Posted in Javascript onNovember 21, 2016

前言

我们引入jQuery来进行异步上传可以获得更好的用户体验。 一方面,在JavaScript中进行异步操作比表单更加灵活; 另一方面,异步上传也避免了上传大文件时的页面长时间卡死。

HTML

一个type=file<input>就可以让用户来浏览并选择文件, 一般会把输入控件放到一个<form>中,下面的一个简单的表单:

<form>
 <input type="file" id="avatar" name="avatar">
 <button type="button">保存</button>
</form>

但为什么我只能选择一个文件??给<input>添加一个multiple属性就可以多选了!

<input type="file" id="avatar" name="avatar" multiple>

获取文件列表

上述的<input>将会拥有一个叫files的DOM属性,包含了所选的文件列表(Array)。

$('button').click(function(){
 var $input = $('#avatar');
 // 相当于: $input[0].files, $input.get(0).files
 var files = $input.prop('files');
 console.log(files);
});

这个Array中的每一项都是一个File对象,它有下面几个主要属性:

     name: 文件名,只读字符串,不包含任何路径信息.

     size: 文件大小,单位为字节,只读的64位整数.

     type: MIME类型,只读字符串,如果类型未知,则返回空字符串.

详情可以参考:https://developer.mozilla.org/zh-CN/docs/Using_files_from_web_applications

multipart/form-data

上传文件比较特殊,其内容是二进制数据,而HTTP提供的是基于文本的通信协议。 这时需要采用multipart/form-data编码的HTTP表单。

其HTTP消息体格式如下所示:

------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="title"

harttle
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="avatar"; filename="harttle.png"
Content-Type: image/png

 ... content of harttle.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

每个字段由一段boundary string来分隔,浏览器保证该boundary string不与内容重复, 因而multipart/form-data能够成功编码二进制数据。

jQuery上传文件

这是XMLHttpRequest Level 2提供的FormData对象可以帮助我们进行二进制文件的 multipart/form-data编码:

$('button').click(function(){
 var files = $('#avatar').prop('files');

 var data = new FormData();
 data.append('avatar', files[0]);

 $.ajax({
  url: '/api/upload',
  type: 'POST',
  data: data,
  cache: false,
  processData: false,
  contentType: false
 });
});

url, type, data想必做前端的都很熟悉了,介绍其余三个参数:

cache

cache设为false可以禁止浏览器对该URL(以及对应的HTTP方法)的缓存。 jQuery通过为URL添加一个冗余参数来实现。

该方法只对GET和HEAD起作用,然而IE8会缓存之前的GET结果来响应POST请求。 这里设置cache: false是为了兼容IE8。

参考:http://api.jquery.com/jquery.ajax/

contentType

jQuery中content-type默认值为application/x-www-form-urlencoded, 因此传给data参数的对象会默认被转换为query string(见HTTP 表单编码 enctype)。

我们不需要jQuery做这个转换,否则会破坏掉multipart/form-data的编码格式。 因此设置contentType: false来禁止jQuery的转换操作。

processData

jQuery会将data对象转换为字符串来发送HTTP请求,默认情况下会用 application/x-www-form-urlencoded编码来进行转换。 我们设置contentType: false后该转换会失败,因此设置processData: false来禁止该转换过程。

我们给的data就是已经用FormData编码好的数据,不需要jQuery进行字符串转换。

兼容性与其他选择

本文介绍的jQuery文件上传方式依赖于FormData对象, 这是XMLHttpRequest Level 2接口, 需要 IE 10+, Firefox 4.0+, Chrome 7+, Safari 5+, Opera 12+

这意味着对于低版本浏览器只能使用直接提交文件表单的形式, 但提交大文件表单页面会长时间不响应,如果希望在低版本浏览器中解决该问题, 就只能使用别的方式来实现了,比如很多支持多文件和上传进度的Flash插件。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
可以把编码转换成 gb2312编码lib.UTF8toGB2312.js
Aug 21 Javascript
JavaScript 拖拉缩放效果
Dec 10 Javascript
JavaScript 学习笔记(四)
Dec 31 Javascript
IE6不能修改NAME问题的解决方法
Sep 03 Javascript
Javascript浅谈之引用类型
Dec 18 Javascript
angularJS提交表单(form)
Feb 09 Javascript
浅谈JavaScript的Polymer框架中的事件绑定
Jul 29 Javascript
jQuery仅用3行代码实现的显示与隐藏功能完整实例
Oct 08 Javascript
JavaScript生成验证码并实现验证功能
Sep 24 Javascript
详解从Node.js的child_process模块来学习父子进程之间的通信
Mar 27 Javascript
vue2.0实现分页组件的实例代码
Jun 22 Javascript
JavaScript中的LHS和RHS分析详情
Apr 06 Javascript
遍历js中对象的属性和值的实例
Nov 21 #Javascript
JavaScript数据结构链表知识详解
Nov 21 #Javascript
jQuery简单自定义图片轮播插件及用法示例
Nov 21 #Javascript
Node.js测试中的Mock文件系统详解
Nov 21 #Javascript
JavaScript中boolean类型之三种情景实例代码
Nov 21 #Javascript
基于jQuery实现Tabs选项卡自定义插件
Nov 21 #Javascript
基于jQuery实现Accordion手风琴自定义插件
Oct 13 #Javascript
You might like
php随机生成数字字母组合的方法
2015/03/18 PHP
PHP传值到不同页面的三种常见方式及php和html之间传值问题
2015/11/19 PHP
PHP实现限制IP访问的方法
2017/04/20 PHP
浅析PHP7 的垃圾回收机制
2019/09/06 PHP
神奇的代码 通杀各种网站-可随意修改复制页面内容
2008/07/17 Javascript
javascript 无提示关闭窗口脚本
2009/08/17 Javascript
JavaScript 比较时间大小的代码
2010/04/24 Javascript
封装html的select标签的js操作实例
2013/07/02 Javascript
浅谈JavaScript Math和Number对象
2015/01/26 Javascript
完美兼容多浏览器的js判断图片路径代码汇总
2015/04/17 Javascript
jQuery实现下拉框功能实例代码
2016/05/06 Javascript
AngularJS基于ui-route实现深层路由的方法【路由嵌套】
2016/12/14 Javascript
jquery仿ps颜色拾取功能
2017/03/08 Javascript
JavaScript变量声明var,let.const及区别浅析
2018/04/23 Javascript
axios+Vue实现上传文件显示进度功能
2019/04/14 Javascript
JavaScript对象原型链原理详解
2020/02/05 Javascript
微信小程序自定义tabBar的踩坑实践记录
2020/11/06 Javascript
[56:20]LGD vs VP Supermajor 败者组决赛 BO3 第三场 6.10
2018/07/04 DOTA
请不要重复犯我在学习Python和Linux系统上的错误
2016/12/12 Python
Python实现读取邮箱中的邮件功能示例【含文本及附件】
2017/08/05 Python
python中for循环输出列表索引与对应的值方法
2018/11/07 Python
[机器视觉]使用python自动识别验证码详解
2019/05/16 Python
Python解析json时提示“string indices must be integers”问题解决方法
2019/07/31 Python
Tensorflow中k.gradients()和tf.stop_gradient()用法说明
2020/06/10 Python
如何教少儿学习Python编程
2020/07/10 Python
python搜索算法原理及实例讲解
2020/11/18 Python
关于pycharm 切换 python3.9 报错 ‘HTMLParser‘ object has no attribute ‘unescape‘ 的问题
2020/11/24 Python
美国在线和移动免费会员制批发零售商:Boxed(移动端的Costco)
2020/01/02 全球购物
linux下进程间通信的方式
2014/12/23 面试题
对外汉语专业大学生职业生涯规划范文
2014/09/13 职场文书
2015年创先争优工作总结
2015/05/23 职场文书
三十年同学聚会致辞
2015/07/28 职场文书
小学音乐课教学反思
2016/02/18 职场文书
导游词之泰山玉皇顶
2019/12/23 职场文书
Python离线安装openpyxl模块的步骤
2021/03/30 Python
关于vue-router-link选择样式设置
2022/04/30 Vue.js