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

1,先看效果图

期望的功能和效果很简单:点击页面中的上传文件表单控件,选择文件后点击“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: 'upload01.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都是空数组,php://input也是null
if (isset($_FILES['myfile']) && !empty($_FILES['myfile'])) {
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

关于 Content-Type:application/x-www-form-urlencoded 和 Content-Type:multipart/related


基于jQuery的ajax系列之用FormData实现页面无刷新上传的更多相关文章

  1. ajax+FormData+javascript 实现无刷新上传附件

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  2. jquery ajax php 无刷新上传文件 带 遮罩 进度条 效果的哟

    在很多项目中都会叫用户上传东西这些的,自从接触了jquery 和ajax之后就不管做什么,首先都会想到这个,我这个人呢?是比较重视客户体验的,这次我这边负责的是后台板块,然后就有一块是要求用户上传照片 ...

  3. jQuery AJAX 网页无刷新上传示例

    新年礼,提供简单.易套用的 jQuery AJAX 上传示例及代码下载.后台对文件的上传及检查,以 C#/.NET Handler 处理 (可视需要改写成 Java 或 PHP). 有时做一个网站项目 ...

  4. jQuery+AJAX实现网页无刷新上传

    新年礼,提供简单.易套用的 jQuery AJAX上传示例及代码下载.后台对文件的上传及检查,以 C#/.NET Handler 处理 (可视需要改写成 Java 或 PHP). 有时做一个网站项目 ...

  5. jQuery+php+ajax实现无刷新上传文件功能

    jQuery+php+ajax实现无刷新上传文件功能,还带有上传进度条动画效果,支持图片.视频等大文件上传. js代码 <script type='text/javascript' src='j ...

  6. [Asp.net mvc]jquery.form.js无刷新上传

    写在前面 最近在自己的网盘项目中想用ajax.beginform的方式做无刷新的操作,提交表单什么的都可以,但针对文件上传,就是个鸡肋.在网上查找了发现很多人都遇到了这个问题,大部分都推荐使用jque ...

  7. jQuery无刷新上传之uploadify简单试用

    先简单的侃两句:貌似已经有两个月的时间没有写过文章了,不过仍会像以前那样每天至少有一至两个小时是泡在园子里看各位大神的文章.前些天在研究“ajax无刷新上传”方面的一些插件,用SWFUpload实现了 ...

  8. ajax无刷新上传和下载

    关于ajax无刷新上传和下载 这是一个没什么含量但是又用的比较多又不得不说的问题,其实真的不想说,因为没什么好说的. 关于上传 1.使用Flash,ActiveX 上传 ,略... 2.自己写XMLH ...

  9. ajax 无刷新上传

    最近要做微信的图文上传,因为一个图文了表中可以有多个图文,所有按钮需要随时添加,所以做了一种无刷新上传的方法. 首先我们要在html页面中写上这样的几段代码 javascript: $(functio ...

随机推荐

  1. Perl基础(1)chop与chomp的区别

    chop是去掉字符串的最后一个字符 chomp是去掉"$/"指定的结尾符号 测试程序一: [perl] #!/bin/perl $tmp = "sincere" ...

  2. 将Model实体类对象作为WebService接口参数(转)

    转自:http://www.cnblogs.com/fengyishou/archive/2009/02/27/1399281.html 关于web服务的有关基础知识,看了基本书,但是不敢在这里乱说, ...

  3. 一行代码解决各种IE兼容问题,IE6,IE7,IE8,IE9,IE10(转载)

    在网站开发中不免因为各种兼容问题苦恼,针对兼容问题,其实IE给出了解决方案Google也给出了解决方案百度也应用了这种方案去解决IE的兼容问题 百度源代码如下 <!Doctype html> ...

  4. 处理程序“svc-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler”

    HTTP 错误 404.3 - Not Found 由于扩展配置问题而无法提供您请求的页面.如果该页面是脚本,请添加处理程序.如果应下载文件,请添加 MIME 映射. 解决办法:以管理员运行命令:C: ...

  5. jQuery获取Radio选择的Value值||两个select之间option的互相添加操作(jquery实现)

    jQuery获取Radio选择的Value值: 1. $("input[name='radio_name'][checked]").val();  //选择被选中Radio的Val ...

  6. 【Oracle】-【ROWNUM与索引】-索引对ROWNUM检索的影响

    看到ASK TOM的一篇文章,挺有感触的. http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:32812348052 ...

  7. ASP.NET WebApi 开放数据

    概述 开放式数据协议(OData) 是用于在 web 数据访问协议.它提供统一的方式来构造数据. 查询的数据和操纵数据集通过 CRUD 操作.它支持 AtomPub (XML) 和 JSON 格式.它 ...

  8. 让VS2010记住TFS的登陆用户名和密码

    用VS进行团队开发的都知道,每次打开VS连接TFS的时候,都要提示输入用户名和密码,每次都这样无疑感觉太多此一举了(当然你不想别人操作你的电脑就直接进入项目就没必要这么做),为了像连接远程那样可以记住 ...

  9. [置顶] 网页提交方式post和get的区别和联系

    都知道GET一般用于获取/查询资源信息,而POST一般用于更新资源信息.但具体区别呢?可以互换吗? 主要区别有:1传输数据的方式不同,2传输的数据多少不同,3传输数据的安全性不同4,后台获取数据的方式 ...

  10. Data Annotations

    Data Annotations   Entity Framework Code First 利用一种被称为约定(Conventions)优于配置(Configuration)的编程模式允许你使用自己 ...