开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
这一章是关于发送 HTML 表单的:带有或不带文件,带有其他字段等。
FormData 对象可以提供帮助。你可能已经猜到了,它是表示 HTML 表单数据的对象。
构造函数是:
let formData = new FormData([form]);
如果提供了 HTML form 元素,它会自动捕获 form 元素字段。
FormData 的特殊之处在于网络方法(network methods),例如 fetch 可以接受一个 FormData 对象作为 body。它会被编码并发送出去,带有 Content-Type: multipart/form-data。
从服务器角度来看,它就像是一个普通的表单提交。
发送一个简单的表单
我们先来发送一个简单的表单。
正如你所看到的,它几乎就是一行代码:
<form id="formElem">
<input type="text" name="name" value="John">
<input type="text" name="surname" value="Smith">
<input type="submit">
</form>
<script>
formElem.onsubmit = async (e) => {
e.preventDefault();
let response = await fetch('/article/formdata/post/user', {
method: 'POST',
body: new FormData(formElem)
});
let result = await response.json();
alert(result.message);
};
</script>
在这个示例中,没有将服务器代码展示出来,因为它超出了我们当前的学习范围。服务器接受 POST 请求并回应 “User saved”。
FormData 方法
我们可以使用以下方法修改 FormData 中的字段:
formData.append(name, value)—— 添加具有给定name和value的表单字段,formData.append(name, blob, fileName)—— 添加一个字段,就像它是<input type="file">,第三个参数fileName设置文件名(而不是表单字段名),因为它是用户文件系统中文件的名称,formData.delete(name)—— 移除带有给定name的字段,formData.get(name)—— 获取带有给定name的字段值,formData.has(name)—— 如果存在带有给定name的字段,则返回true,否则返回false。
从技术上来讲,一个表单可以包含多个具有相同 name 的字段,因此,多次调用 append 将会添加多个具有相同名称的字段。
还有一个 set 方法,语法与 append 相同。不同之处在于 .set 移除所有具有给定 name 的字段,然后附加一个新字段。因此,它确保了只有一个具有这种 name 的字段,其他的和 append 一样:
formData.set(name, value),formData.set(name, blob, fileName)。
我们也可以使用 for..of 循环迭代 formData 字段:
let formData = new FormData();
formData.append('key1', 'value1');
formData.append('key2', 'value2');
// 列出 key/value 对
for(let [name, value] of formData) {
alert(`${name} = ${value}`); // key1 = value1,然后是 key2 = value2
}
发送带有文件的表单
表单始终以 Content-Type: multipart/form-data 来发送数据,这个编码允许发送文件。因此 <input type="file"> 字段也能被发送,类似于普通的表单提交。
这是具有这种形式的示例:
<form id="formElem">
<input type="text" name="firstName" value="John">
Picture: <input type="file" name="picture" accept="image/*">
<input type="submit">
</form>
<script>
formElem.onsubmit = async (e) => {
e.preventDefault();
let response = await fetch('/article/formdata/post/user-avatar', {
method: 'POST',
body: new FormData(formElem)
});
let result = await response.json();
alert(result.message);
};
</script>