FormData 对象
1.概述
表单数据以键值对的形式向服务器发送,这个过程是浏览器自动完成的。但是有时候,我们希望通过脚本完成过程,构造和编辑表单键值对,然后通过XMLHttpRequest.send()方法发送。浏览器原生提供了 FormData 对象来完成这项工作。
1. 构造函数创建一个formData对象实例
var formdata = new FormData(form);
FormData()构造函数的参数是一个表单元素,这个参数是可选的。如果省略参数,就表示一个空的表单,否则就会处理表单元素里面的键值对。
2. 使用已有的表单来初始化一个对象实例
下面是一个表单。
<form id="myForm" name="myForm">
<div>
<label for="username">用户名:</label>
<input type="text" id="username" name="username">
</div>
<div>
<label for="useracc">账号:</label>
<input type="text" id="useracc" name="useracc">
</div>
<div>
<label for="userfile">上传文件:</label>
<input type="file" id="userfile" name="userfile">
</div>
<input type="submit" value="Submit!">
</form>
我们用 FormData 对象处理上面这个表单。
var myForm = document.getElementById('myForm');
var formData = new FormData(myForm);
// 获取某个控件的值
formData.get('username') // ""
// 设置某个控件的值
formData.set('username', '张三');
formData.get('username') // "张三"
2.实例方法
FormData 提供以下实例方法。
FormData.get(key):
获取指定键名对应的键值,参数为键名。如果有多个同名的键值对,则返回第一个键值对的键值。
FormData.getAll(key):
返回一个数组,表示指定键名对应的所有键值。如果有多个同名的键值对,数组会包含所有的键值。
FormData.set(key, value):
设置指定键名的键值,参数为键名。如果键名不存在,会添加这个键值对,否则会更新指定键名的键值。如果第二个参数是文件,还可以使用第三个参数,表示文件名。
FormData.delete(key):
删除一个键值对,参数为键名。
FormData.append(key, value):
添加一个键值对。如果键名重复,则会生成两个相同键名的键值对。如果第二个参数是文件,还可以使用第三个参数,表示文件名。
FormData.has(key):
返回一个布尔值,表示是否具有该键名的键值对。
FormData.keys():
返回一个遍历器对象,用于for…of循环遍历所有的键名。
FormData.values():
返回一个遍历器对象,用于for…of循环遍历所有的键值。
FormData.entries():
返回一个遍历器对象,用于for…of循环遍历所有的键值对。如果直接用for…of循环遍历
FormData 实例,默认就会调用这个方法。
for (var pair of formData.entries()) {
console.log(pair[0] + ': ' + pair[1]);
}
// key1: value1
// key2: value2
// 等同于遍历 formData.entries()
for (var pair of formData) {
console.log(pair[0] + ': ' + pair[1]);
}
// key1: value1
// key2: value2
3.文件上传
用户上传文件,也是通过表单。具体来说,就是通过文件输入框选择本地文件,提交表单的时候,浏览器就会把这个文件发送到服务器。
<input type="file" id="file" name="myFile">
此外,还需要将表单元素的method属性设为POST,enctype属性设为multipart/form-data。其中,enctype属性决定了 HTTP 头信息的Content-Type字段的值,默认情况下这个字段的值是application/x-www-form-urlencoded,但是文件上传的时候要改成multipart/form-data。
<form method="post" enctype="multipart/form-data">
<div>
<label for="file">选择一个文件</label>
<input type="file" id="file" name="myFile" multiple>
</div>
<div>
<input type="submit" id="submit" name="submit_button" value="上传" />
</div>
</form>
上面的 HTML 代码中,file 控件的multiple属性,指定可以一次选择多个文件;如果没有这个属性,则一次只能选择一个文件。
var fileSelect = document.getElementById('file');
var files = fileSelect.files;
然后,新建一个 FormData 实例对象,模拟发送到服务器的表单数据,把选中的文件添加到这个对象上面。
var formData = new FormData();
for (var i = 0; i < files.length; i++) {
var file = files[i];
// 只上传图片文件
if (!file.type.match('image.*')) {
continue;
}
formData.append('photos', file, file.name);
}
最后,使用 Ajax 向服务器上传文件。
var xhr = new XMLHttpRequest();
xhr.open('POST', 'handler.php', true);
xhr.onload = function () {
if (xhr.status !== 200) {
console.log('An error occurred!');
}
};
xhr.send(formData);
除了发送 FormData 实例,也可以直接 AJAX 发送指定格式文件。
var file = document.getElementById('test-input').files[0];
var xhr = new XMLHttpRequest();
xhr.open('POST', 'myserver/uploads');
//file.type 这里指定了file的类型,为默认上传的类型
例如: image/gif :gif图片格式
image/jpeg :jpg图片格式
image/png:png图片格式
xhr.setRequestHeader('Content-Type', file.type);
xhr.send(file);
4.表单设置enctype 属性
表单能够用四种编码,向服务器发送数据。编码格式由表单的enctype属性决定。
假定表单有两个字段,分别是foo和baz,其中foo字段的值等于bar,baz字段的值是一个分为两行的字符串。
The first line.
The second line.
下面四种格式,都可以将这个表单发送到服务器。
(1)GET 方法
如果表单使用GET方法发送数据,enctype属性无效。
<form
action="register.php"
method="get"
onsubmit="AJAXSubmit(this); return false;"
>
</form>
数据将以 URL 的查询字符串发出。
?foo=bar&baz=The%20first%20line.%0AThe%20second%20line.
(2)application/x-www-form-urlencoded
如果表单用POST方法发送数据,并省略enctype属性,那么数据以application/x-www-form-urlencoded格式发送(因为这是默认值)。
<form
action="register.php"
method="post"
onsubmit="AJAXSubmit(this); return false;"
>
</form>
发送的 HTTP 请求如下。
Content-Type: application/x-www-form-urlencoded
foo=bar&baz=The+first+line.%0D%0AThe+second+line.%0D%0A
上面代码中,数据体里面的%0D%0A代表换行符(\r\n)。
(3)text/plain
如果表单使用POST方法发送数据,enctype属性为text/plain,那么数据将以纯文本格式发送。
<form
action="register.php"
method="post"
enctype="text/plain"
onsubmit="AJAXSubmit(this); return false;"
>
</form>
发送的 HTTP 请求如下。
Content-Type: text/plain
foo=bar
baz=The first line.
The second line.
(4)multipart/form-data
如果表单使用POST方法,enctype属性为multipart/form-data,那么数据将以混合的格式发送。
<form
action="register.php"
method="post"
enctype="multipart/form-data"
onsubmit="AJAXSubmit(this); return false;"
>
</form>
发送的 HTTP 请求如下。
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--
这种格式也是文件上传的格式。