使用 FormData 对象
FormData 对象允许您编译一组键/值对,以便使用 Fetch 或 XMLHttpRequest API 进行发送。它主要用于发送表单数据,但也可以独立于表单使用,以传输键控数据。传输的数据格式与表单的 submit() 方法在表单编码类型设置为 multipart/form-data 时发送数据所使用的格式相同。
从头开始创建 FormData 对象
您可以自己构建 FormData 对象,实例化它,然后通过调用其 append() 方法来追加字段,如下所示:
const send = document.querySelector("#send");
send.addEventListener("click", async () => {
const formData = new FormData();
formData.append("username", "Groucho");
formData.append("accountNum", 123456);
// A file <input> element
const avatar = document.querySelector("#avatar");
formData.append("avatar", avatar.files[0]);
// JavaScript file-like object
const content = '<q id="a"><span id="b">hey!</span></q>';
const blob = new Blob([content], { type: "text/xml" });
formData.append("webmasterFile", blob);
const response = await fetch("http://example.org/post", {
method: "POST",
body: formData,
});
console.log(await response.json());
});
注意: 字段 "avatar" 和 "webmasterFile" 都包含一个文件。分配给字段 "accountNum" 的数字会立即被 FormData.append() 方法转换为字符串(字段的值可以是 Blob、File 或字符串。如果值既不是 Blob 也不是 File,则该值将被转换为字符串)。
此示例构建了一个 FormData 实例,其中包含名为 "username"、"accountNum"、"avatar" 和 "webmasterFile" 的字段的值,然后使用 fetch() 发送表单数据。字段 "webmasterFile" 是一个 Blob。Blob 对象代表一个文件类对象,包含不可变的原始数据。Blob 代表的数据不一定是 JavaScript 原生格式。 File 接口基于 Blob,继承了 Blob 的功能并对其进行了扩展,以支持用户系统上的文件。为了构建一个 Blob,您可以调用 Blob() 构造函数。
从 HTML 表单检索 FormData 对象
要构造一个包含现有 <form> 数据的 FormData 对象,请在创建 FormData 对象时指定该表单元素。
注意: FormData 只会使用带有 name 属性的输入字段。
const formData = new FormData(someFormElement);
例如
const send = document.querySelector("#send");
send.addEventListener("click", async () => {
// A <form> element
const userInfo = document.querySelector("#user-info");
const formData = new FormData(userInfo);
const response = await fetch("http://example.org/post", {
method: "POST",
body: formData,
});
console.log(await response.json());
});
您也可以在从表单检索 FormData 对象并发送它之前,追加额外数据,如下所示:
const send = document.querySelector("#send");
send.addEventListener("click", async () => {
const userInfo = document.querySelector("#user-info");
const formData = new FormData(userInfo);
formData.append("serialnumber", 12345);
const response = await fetch("http://example.org/post", {
method: "POST",
body: formData,
});
console.log(await response.json());
});
这允许您在发送表单数据之前对其进行增强,以包含不一定是用户可编辑的额外信息。
使用 FormData 对象发送文件
您还可以使用 FormData 发送文件。在您的 <form> 中包含一个类型为 file 的 <input> 元素。
<form enctype="multipart/form-data" method="post" name="fileinfo" id="fileinfo">
<p>
<label
>Your email address:
<input
type="email"
autocomplete="on"
name="userid"
placeholder="email"
required
size="32"
maxlength="64" />
</label>
</p>
<p>
<label
>Custom file label:
<input type="text" name="file-label" size="12" maxlength="32" />
</label>
</p>
<p>
<label
>File to stash:
<input type="file" name="file" required />
</label>
</p>
<p>
<input type="submit" value="Stash the file!" />
</p>
</form>
然后,您可以使用如下代码发送它:
const form = document.querySelector("#fileinfo");
form.addEventListener("submit", async (event) => {
const formData = new FormData(form);
formData.append("CustomField", "This is some extra data");
const response = await fetch("stash.php", {
method: "POST",
body: formData,
});
event.preventDefault();
});
注意: 如果您传递表单的引用,则表单中指定的 请求 HTTP 方法将优先于 open() 调用中指定的方法。
警告: 当使用 FormData 使用 XMLHttpRequest 或 Fetch API 和 multipart/form-data 内容类型提交 POST 请求时(例如,上传文件和 Blobs 到服务器时),*请不要*显式设置请求的 Content-Type 标头。这样做会阻止浏览器能够设置 Content-Type 标头以及用于分隔请求正文中的表单字段的边界表达式。
您也可以直接将 File 或 Blob 追加到 FormData 对象,如下所示:
data.append("myfile", myBlob, "filename.txt");
当使用 append() 方法时,可以使用第三个可选参数在发送到服务器的 Content-Disposition 标头中传递文件名。当未指定文件名时(或参数不受支持时),将使用名称 "blob"。
使用 formdata 事件
formdata 事件比 FormData 对象出现得更晚,它在一个 HTMLFormElement 对象上触发,在表示表单数据条目的列表构造完成后。这发生在表单提交时,但也可以通过调用 FormData() 构造函数来触发。
这使得可以快速获得一个 FormData 对象作为对 formdata 事件触发的响应,而无需自己进行组装。
例如,在 JavaScript 中,我们可以引用一个表单:
const formElem = document.querySelector("form");
在我们的 submit 事件处理程序中,我们使用 preventDefault 来阻止默认的表单提交,然后调用 FormData() 构造函数来触发 formdata 事件。
formElem.addEventListener("submit", (e) => {
// on form submission, prevent default
e.preventDefault();
// construct a FormData object, which fires the formdata event
new FormData(formElem);
});
当 formdata 事件触发时,我们可以通过 FormDataEvent.formData 访问 FormData 对象,然后对其进行任何我们想要的操作(下面我们使用 XMLHttpRequest 将其发布到服务器)。
formElem.addEventListener("formdata", (e) => {
console.log("formdata fired");
// Get the form data from the event object
const data = e.formData;
for (const value of data.values()) {
console.log(value);
}
// Submit the data via fetch()
fetch("/formHandler", {
method: "POST",
body: data,
});
});
注意事项
FormData 对象不包含禁用字段或禁用 fieldsets 的数据。