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 相关文章推荐
javascript 多浏览器 事件大全
Mar 23 Javascript
Js获取数组最大和最小值示例代码
Oct 29 Javascript
jquery加载图片时以淡入方式显示的方法
Jan 14 Javascript
深入浅析JavaScript中数据共享和数据传递
Apr 25 Javascript
浅谈js中子页面父页面方法 变量相互调用
Aug 04 Javascript
BootStrap下拉框在firefox浏览器界面不友好的解决方案
Aug 18 Javascript
实现JavaScript高性能的数据存储
Dec 11 Javascript
JavaScript实现HTML5游戏断线自动重连的方法
Sep 18 Javascript
图文介绍Vue父组件向子组件传值
Feb 17 Javascript
Vue实现todolist删除功能
Jun 26 Javascript
JavaScript实现获取两个排序数组的中位数算法示例
Feb 26 Javascript
webpack3升级到webpack4遇到问题总结
Sep 30 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 图片水印类代码
2012/08/27 PHP
深入解析yii权限分级式访问控制的实现(非RBAC法)
2013/06/13 PHP
PHP基于MySQL数据库实现对象持久层的方法
2015/06/17 PHP
php模仿qq空间或朋友圈发布动态、评论动态、回复评论、删除动态或评论的功能(中)
2017/06/11 PHP
Laravel框架实现model层的增删改查(CURD)操作示例
2018/05/12 PHP
PHP从零开始打造自己的MVC框架之路由类实现方法分析
2019/06/03 PHP
javascript firefox不显示本地预览图片问题的解决方法
2008/11/12 Javascript
javascript div 弹出可拖动窗口
2009/02/26 Javascript
通过继承IHttpHandle实现JS插件的组织与管理
2010/07/13 Javascript
使用jquery动态加载javascript以减少服务器压力
2012/10/29 Javascript
js格式化金额可选是否带千分位以及保留精度
2014/01/28 Javascript
JQuery记住用户名和密码的具体实现
2014/04/04 Javascript
JavaScript数组各种常见用法实例分析
2015/08/04 Javascript
JS Array创建及concat()split()slice()的使用方法
2016/06/03 Javascript
浅谈js数据类型判断与数组判断
2016/08/29 Javascript
JS实现表单验证功能(验证手机号是否存在,验证码倒计时)
2016/10/11 Javascript
jQuery+pjax简单示例汇总
2017/04/21 jQuery
讲解vue-router之命名路由和命名视图
2018/05/28 Javascript
微信小程序sessionid不一致问题解决
2019/08/30 Javascript
vue父组件给子组件的组件传值provide inject的方法
2019/10/23 Javascript
pandas实现将dataframe满足某一条件的值选出
2019/06/12 Python
教你一步步利用python实现贪吃蛇游戏
2019/06/27 Python
在Python中获取操作系统的进程信息
2019/08/27 Python
python如何删除文件、目录
2020/06/23 Python
理解Django 中Call Stack机制的小Demo
2020/09/01 Python
HTML5 audio标签使用js进行播放控制实例
2015/04/24 HTML / CSS
YII2 全局异常处理深入讲解
2021/03/24 PHP
网络工程师个人的自我评价范文
2013/10/01 职场文书
大学生职业生涯设计书
2014/01/02 职场文书
上课迟到检讨书
2014/01/19 职场文书
我的老师教学反思
2014/05/01 职场文书
新闻发布会活动策划方案
2014/09/15 职场文书
家装业务员岗位职责
2015/04/03 职场文书
2016公司中秋节寄语
2015/12/07 职场文书
golang操作rocketmq的示例代码
2022/04/06 Golang
Flutter Navigator 实现路由传递参数
2022/04/22 Java/Android