使用 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 的資料。