AJAX 异步提交数据有很多优点,那么怎样在表单中使用 AJAX 异步上传图片呢。本文对关键技术进行讲解。
首先贴上正确代码,然后对其中的重要地方进行说明。
<input type="file" id="file">
<script src="jquery.min.js"></script>
<script>
$("#file").change(function () {
var file = document.getElementById("file").files[0]; // 只上传一个文件
//var file = $("#file")[0].files[0]; // 和上面结果一样
var formData = new FormData(); // 实例化一个 FormData 对象
formData.append('file', file); // 按键值对组装数据
$.ajax({
url: 'http://seller.test/api/v1/image/upload',
type: "POST",
data: formData,
processData: false,
contentType: false,
success: function (data) {
console.info(data);
}
})
});
</script>
类型:Boolean
,默认为 true。默认情况下,通过 data 选项传递进来的数据,如果是一个对象(技术上讲只要不是字符串),都会转化成一个查询字符串,来配合默认的编码格式 application/x-www-form-urlencoded
。如果要发送 DOM 树信息或者其它不希望转换的信息(比如二进制数据),需要将其设置为 false。
类型:String/Boolean
,默认值 application/x-www-form-urlencoded
,HTTP 协议发送内容时的编码格式。如果设置了这个值,将在请求头中显式的将其发送给服务器(即使没有数据要发送)。
利用 FormData 对象,我们可以通过 JavaScript 用一些键值对来模拟一系列表单控件。比起普通的 ajax,使用 FormData 的最大优点是我们可以异步上传一个二进制文件。
POST 请求,将 enctype 属性设置为 application/x-www-form-urlencode
,即默认的传输格式
Content-Type: application/x-www-form-urlencoded
foo=bar&baz=The+first+line.%0D%0AThe+second+line.%0D%0A
POST 请求,将 enctype 属性设置为 text/plain
Content-Type: text/plain
foo=bar
baz=The first line.
The second line.
POST 请求,将 enctype 属性设置为 multipart/form-data
Content-Type: multipart/form-data; boundary=---------------------------314911788813839
-----------------------------314911788813839
Content-Disposition: form-data; name="foo"
bar
-----------------------------314911788813839
Content-Disposition: form-data; name="baz"
The first line.
The second line.
-----------------------------314911788813839--
GET 请求
类似 ?foo=bar&baz=The%20first%20line.%0AThe%20second%20line.
的参数会被添加到 URL 后面。
这是 HTTP 协议的一部分,具体可以看见 HTTP 协议详解(三) 。
我们使用的是 multipart/form-data
格式来传输文件数据的,注意 Content-Type
,值为 multipart/form-data
,紧接着后面还有一个内容分界线标识,用来分隔数据,两个分隔线之间就是一个完整的数据对象,参看上面的代码示例。这就是为什么将 enctype 属性设置为 multipart/form-data
时,数据传输出错的原因,因为设置了 Content-Type
之后,显式的将值变成 multipart/form-data
,而少了后面的分界线标识,造成服务的无法正确接收数据。其实看到这里,我们也可以根据 HTTP 协议自行封装文件上传的请求。