使用 FormData 物件

FormData 物件允許您編譯一組鍵/值對,以便使用 FetchXMLHttpRequest API 進行傳送。它主要用於傳送表單資料,但也可以獨立於表單使用,以傳輸鍵控資料。傳輸的資料格式與表單的 submit() 方法在表單編碼型別設定為 multipart/form-data 時傳送資料所使用的格式相同。

從頭開始建立 FormData 物件

您可以自己構建 FormData 物件,例項化它,然後透過呼叫其 append() 方法來追加欄位,如下所示:

js
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() 方法轉換為字串(欄位的值可以是 BlobFile 或字串。如果值既不是 Blob 也不是 File,則該值將被轉換為字串)。

此示例構建了一個 FormData 例項,其中包含名為 "username""accountNum""avatar""webmasterFile" 的欄位的值,然後使用 fetch() 傳送表單資料。欄位 "webmasterFile" 是一個 BlobBlob 物件代表一個檔案類物件,包含不可變的原始資料。Blob 代表的資料不一定是 JavaScript 原生格式。 File 介面基於 Blob,繼承了 Blob 的功能並對其進行了擴充套件,以支援使用者系統上的檔案。為了構建一個 Blob,您可以呼叫 Blob() 建構函式

從 HTML 表單檢索 FormData 物件

要構造一個包含現有 <form> 資料的 FormData 物件,請在建立 FormData 物件時指定該表單元素。

注意: FormData 只會使用帶有 name 屬性的輸入欄位。

js
const formData = new FormData(someFormElement);

例如

js
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 物件併發送它之前,追加額外資料,如下所示:

js
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> 元素。

html
<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>

然後,您可以使用如下程式碼傳送它:

js
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 使用 XMLHttpRequestFetch APImultipart/form-data 內容型別提交 POST 請求時(例如,上傳檔案和 Blobs 到伺服器時),*請不要*顯式設定請求的 Content-Type 標頭。這樣做會阻止瀏覽器能夠設定 Content-Type 標頭以及用於分隔請求正文中的表單欄位的邊界表示式。

您也可以直接將 FileBlob 追加到 FormData 物件,如下所示:

js
data.append("myfile", myBlob, "filename.txt");

當使用 append() 方法時,可以使用第三個可選引數在傳送到伺服器的 Content-Disposition 標頭中傳遞檔名。當未指定檔名時(或引數不受支援時),將使用名稱 "blob"。

使用 formdata 事件

formdata 事件比 FormData 物件出現得更晚,它在一個 HTMLFormElement 物件上觸發,在表示表單資料條目的列表構造完成後。這發生在表單提交時,但也可以透過呼叫 FormData() 建構函式來觸發。

這使得可以快速獲得一個 FormData 物件作為對 formdata 事件觸發的響應,而無需自己進行組裝。

例如,在 JavaScript 中,我們可以引用一個表單:

js
const formElem = document.querySelector("form");

在我們的 submit 事件處理程式中,我們使用 preventDefault 來阻止預設的表單提交,然後呼叫 FormData() 建構函式來觸發 formdata 事件。

js
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 將其釋出到伺服器)。

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

另見