jQuery的ajax中使用FormData实现页面无刷新上传功能


Posted in Javascript onJanuary 16, 2017

接着上一篇ajax系列之用jQuery的ajax方法向服务器发出get和post请求写,这篇主要写如何利用ajax和FormData实现页面无刷新的文件上传效果,主要用到了jQuery的ajax()方法和XMLHttpRequest Level 2的FormData接口。关于FormData,大家可以看MDN文档。

1,先看效果图

jQuery的ajax中使用FormData实现页面无刷新上传功能

期望的功能和效果很简单:点击页面中的上传文件表单控件,选择文件后点击“ajax提交”,将文件上传至服务器,上传成功后,页面给出一个简单的提示。

2,前端的代码

看下html代码:     

<div class="box">
    <div>
     <div class="item">
      <input type="file" name="myfile" style="font-size: 0.7rem;">
     </div>
     <div class="item">
      <button type="button" style="display: block; padding: 4px 18px;" class="btn-default">ajax提交</button>
     </div>
     <div class="item">
      <button type="submit" style="display: block; padding: 4px 18px;" class="btn-default">form提交</button>
     </div>
    </div>
    <div class="prompt" style="font-size: 0.7rem;"></div>
   </div>
   <script src="../../js/jquery-3.1.0.min.js"></script>
   <script src="upload01.js"></script>

代码很简单,需要注意的是页面中没有用到form表单,那么怎么提交数据呢,答案是用FormData来模拟表单中的 <input type="file" name="myfile"> 控件。另外,页面中的样式没有写出来。下面来看下html中引入的upload01.js代码,这个是重点。

upload01.js代码:

$(function($) {
  $('input[name=myfile]').on('change', function(e) {
   $('button[type=button]').on('click', function(e) {
    var formData = new FormData();
    // formData.ppend(name, element);
    formData.append('myfile', $('input[name=myfile]')[0].files[0]);
    $.ajax({
     url: 'upload.php',
     method: 'POST',
     data: formData,
     contentType: false, // 注意这里应设为false
     processData: false,
     cache: false,
     success: function(data) {
     if (JSON.parse(data).result == 1) {
       $('.prompt').html(`文件${JSON.parse(data).filename}已上传成功`);
      }
     },
     error: function (jqXHR) {
      console.log(JSON.stringify(jqXHR));
     }
    })
    .done(function(data) {
     console.log('done');
    })
    .fail(function(data) {
     console.log('fail');
    })
    .always(function(data) {
     console.log('always');
    });
   });
  });
 });

(1) 下面解释下FormData,涉及到了代码的第4、6、10行。

第4行 var formData = new FormData(); 实例化了一个空的FormData对象,可以认为它就是一个form表单,但现在里面什么控件都没有。

第6行 formData.append('myfile', $('input[name=myfile]')[0].files[0]); ,给实例化的formdata对象添加一个控件,注意这里添加的是已有控件 <input type="file" name="myfile" style="font-size: 0.7rem;"> (见html代码第4行)。

FormData.append(name, value, filename)方法可以很方便的以“键-值”对的形式给FormData添加控件,注意第3个参数“上传文名”是可选的,它的具体语法和用法见FormData。

第10行,将实例化的formData作为jQuery.ajax()方法data参数的值传递进去,提交给后端服务器。

(2) 再解释下ajax()方法中的contentType、processData参数。

contentType参数,发起http请求时设置的请求头中的contentType。jQuery.ajax()默认的值为:'application/x-www-form-urlencoded; charset=UTF-8',这个在大多数情况下都是适用的。

但经过测试,保持默认时会报错,因为发送的数据中有input type="file"(上传文件),那么这时contentType应该设置为'multipart/form-data',但如果指定为这个类型服务端(php)就会报这个错误: Warning: Missing boundary in multipart/form-data POST data in Unknown on line 0 。具体原因现在还不清楚,所以这里先将contentType设置为false,即不让jQuery设置contentType。

processData参数,根据jQuery.ajax()文档中的解释,默认情况下,jQuery会处理发送的数据,将数据按照'application/x-www-form-urlencoded'的要求转换为查询字符串,如果要发送的数据是DOMDocument或者不需要处理,就可以设置为false不让jQuery转换数据,我们这里要发送的数据其实就是DOMDocument。

经过测试,如果保持默认(true)的话,在发起请求前js会报错: TypeError: 'append' called on an object that does not implement interface FormData.

另外还有个dataType参数,期望从服务器中返回的数据格式,这里最好也不要指定,而是让jquery自己根据http响应头中的contentType判断,然后返回一个合适的数据类型。指定后不会影响后台程序的逻辑处理,但你在前端接收的数据很可能不是期望的数据,于是js就会报这一类错误: SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data ,这个是将dataType指定为json后报的错误。

3,后端的php代码

后端服务器是nginx,用php来处理发送过来的数据,代码也很简单:

<?php
 // var_dump($_REQUEST); // 为空数组
 // var_dump($_FILES); //不为空 
 // 当使用FormData配合ajax上传文件时,$_REQUEST、$_POST都是null,php://input也是null
 if (isset($_FILES) && !empty($_FILES)) {
  if (move_uploaded_file($_FILES['myfile']['tmp_name'], $_FILES['myfile']['name'])) {
   echo '{"result": 1, "filename": "' . $_FILES['myfile']['name'] . '"}';
  } else {
   echo '{"result": 0}';
  }
 }

代码的逻辑很简单这里就不多解释了。主要说下我在调试程序时遇到的问题,遇到的问题总结起来就一句话:当使用FormData配合ajax上传文件时,$_REQUEST、$_POST都是空数组,php://input也是null。可以看到,我在代码中的第2、3、5行也写了相关的注释。为什么$_REQUEST会是空呢?我查了些资料,但没找到原因,以后再找原因吧。

以上所述是小编给大家介绍的jQuery的ajax中使用FormData实现页面无刷新上传功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
js 创建快捷方式的代码(fso)
Nov 19 Javascript
判断某个字符在一个字符串中是否存在的js代码
Feb 28 Javascript
JS自定义对象实现Java中Map对象功能的方法
Jan 20 Javascript
jQuery使用hide方法隐藏页面上指定元素的方法
Mar 30 Javascript
Express实现前端后端通信上传图片之存储数据库(mysql)傻瓜式教程(一)
Dec 10 Javascript
Ionic快速安装教程
Jun 03 Javascript
bootstarp modal框居中显示的实现代码
Feb 18 Javascript
javascript修改浏览器title方法 JS动态修改浏览器标题
Nov 30 Javascript
vue组件(全局,局部,动态加载组件)
Sep 02 Javascript
uni-app微信小程序登录授权的实现
May 22 Javascript
解决vue组件没显示,没起作用,没报错,但该显示的组件没显示问题
Sep 02 Javascript
在webstorm中配置less的方法详解
Sep 25 Javascript
Node.js中用D3.js的方法示例
Jan 16 #Javascript
JavaScript实现的select点菜功能示例
Jan 16 #Javascript
使用AngularJS 跨站请求如何解决jsonp请求问题
Jan 16 #Javascript
JavaScript基于DOM操作实现简单的数学运算功能示例
Jan 16 #Javascript
js实现弹窗暗层效果
Jan 16 #Javascript
js实现简单的计算器功能
Jan 16 #Javascript
Javascript中document.referrer隐藏来源的方法
Jan 16 #Javascript
You might like
PHP计数器的实现代码
2013/06/08 PHP
Zend Framework教程之Application和Bootstrap用法详解
2016/03/10 PHP
PHP实现支持加盐的图片加密解密
2016/09/09 PHP
微信公众号开发之获取位置信息php代码
2018/06/13 PHP
JavaScript调用Activex控件的事件的实现方法
2010/04/11 Javascript
为jQuery.Treeview添加右键菜单的实现代码
2010/10/22 Javascript
阻止事件(取消浏览器对事件的默认行为并阻止其传播)
2013/11/03 Javascript
Jquery实现地铁线路指示灯提示牌效果的方法
2015/03/02 Javascript
ECMAScript6中Map/WeakMap详解
2015/06/12 Javascript
使用JavaScript和CSS实现文本隔行换色的方法
2015/11/04 Javascript
javascript中闭包(Closure)详解
2016/01/06 Javascript
js中利用cookie实现记住密码功能
2020/08/20 Javascript
利用React-router+Webpack快速构建react程序
2016/10/27 Javascript
详解使用grunt完成requirejs的合并压缩和js文件的版本控制
2017/03/02 Javascript
Bootstrap 模态对话框只加载一次 remote 数据的完美解决办法
2017/07/09 Javascript
node中koa中间件机制详解
2017/08/22 Javascript
zTree异步加载展开第一级节点的实现方法
2017/09/05 Javascript
js 两个日期比较相差多少天的实例
2017/10/19 Javascript
用WebStorm进行Angularjs 2开发(环境篇:Windows 10,Angular-cli方式)
2018/12/05 Javascript
vue动态添加路由addRoutes之不能将动态路由存入缓存的解决
2019/02/19 Javascript
详解Node.js一行命令上传本地文件到服务器
2019/04/22 Javascript
Python备份Mysql脚本
2008/08/11 Python
python如何通过实例方法名字调用方法
2018/03/21 Python
自适应线性神经网络Adaline的python实现详解
2019/09/30 Python
Django实现网页分页功能
2019/10/31 Python
python脚本实现mp4中的音频提取并保存在原目录
2020/02/27 Python
对Keras中predict()方法和predict_classes()方法的区别说明
2020/06/09 Python
Restful_framework视图组件代码实例解析
2020/11/17 Python
在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern "C"
2014/08/09 面试题
餐饮业会计岗位职责
2013/12/19 职场文书
家教广告词
2014/03/19 职场文书
2015年机关后勤工作总结
2015/05/26 职场文书
高效课堂教学反思
2016/02/24 职场文书
css3 选择器
2022/05/11 HTML / CSS
解决Python保存文件名太长OSError: [Errno 36] File name too long
2022/05/11 Python
如何基于python实现单目三维重建详解
2022/06/25 Python