使用 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
,则该值将转换为字符串)。
此示例构建了一个包含名为 "username"
、"accountnum"
、"avatar"
和 "webmasterfile"
字段值的 FormData
实例,然后使用 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="filelabel" 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()
调用中指定的 method。
警告: 当使用 FormData
以 multipart/form-data
内容类型提交使用 XMLHttpRequest 或 Fetch API 的 POST 请求时(例如,将文件和 Blob 上传到服务器),不要在请求上显式设置 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
对象不包括来自被禁用的字段或被禁用的字段集的数据。