Verwendung von FormData-Objekten

Das FormData Objekt ermöglicht es Ihnen, eine Reihe von Schlüssel/Wert-Paaren zusammenzustellen, die mithilfe der Fetch oder XMLHttpRequest API gesendet werden können. Es ist hauptsächlich dafür gedacht, Formulardaten zu senden, kann jedoch auch unabhängig von Formularen verwendet werden, um mit Schlüsseln versehene Daten zu übertragen. Die übertragenen Daten sind im gleichen Format, das die submit()-Methode des Formulars verwenden würde, wenn der Codierungstyp des Formulars auf multipart/form-data gesetzt wäre.

Erstellen eines FormData-Objekts von Grund auf

Sie können ein FormData-Objekt selbst erstellen, indem Sie es instanziieren und anschließend Felder hinzufügen, indem Sie die append()-Methode aufrufen, wie folgt:

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());
});

Hinweis: Die Felder "avatar" und "webmasterFile" beinhalten beide eine Datei. Die Nummer, die dem Feld "accountNum" zugewiesen wird, wird von der FormData.append()-Methode sofort in einen String umgewandelt (der Wert des Feldes kann ein Blob, File oder ein String sein. Wenn der Wert weder ein Blob noch eine File ist, wird der Wert in einen String umgewandelt).

Dieses Beispiel erstellt eine FormData-Instanz mit Werten für Felder mit den Namen "username", "accountNum", "avatar" und "webmasterFile", und verwendet dann fetch(), um die Daten des Formulars zu senden. Das Feld "webmasterFile" ist ein Blob. Ein Blob-Objekt repräsentiert ein dateiähnliches Objekt mit unveränderlichen rohen Daten. Blobs stellen Daten dar, die nicht notwendigerweise im nativen JavaScript-Format vorliegen. Das File-Interface basiert auf Blob, erbt die Blob-Funktionalitäten und erweitert sie, um Dateien auf dem System des Benutzers zu unterstützen. Um ein Blob zu erstellen, können Sie den den Blob()-Konstruktor aufrufen.

Abrufen eines FormData-Objekts aus einem HTML-Formular

Um ein FormData-Objekt zu erstellen, das die Daten eines vorhandenen <form> enthält, müssen Sie dieses Formularelement angeben, wenn Sie das FormData-Objekt erstellen:

Hinweis: FormData verwendet nur Eingabefelder, die das name-Attribut verwenden.

js
const formData = new FormData(someFormElement);

Beispielsweise:

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());
});

Sie können dem FormData-Objekt auch zusätzliche Daten hinzufügen, nachdem Sie es aus einem Formular abgerufen haben und bevor Sie es senden, wie folgt:

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());
});

Dies ermöglicht es Ihnen, die Daten des Formulars vor dem Versenden zu erweitern, um zusätzliche Informationen einzuschließen, die nicht unbedingt vom Benutzer bearbeitet werden können.

Senden von Dateien mit einem FormData-Objekt

Sie können auch Dateien mit FormData senden. Fügen Sie in Ihrem <form> ein <input>-Element vom Typ file ein:

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>

Dann können Sie es mit einem Code wie dem folgenden senden:

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();
});

Hinweis: Wenn Sie eine Referenz auf das Formular übergeben, wird die HTTP-Anfragemethode, die im Formular angegeben ist, anstelle der in dem open()-Aufruf angegebenen Methode verwendet.

Warnung: Beim Verwenden von FormData zum Übermitteln von POST-Anfragen mithilfe von XMLHttpRequest oder der Fetch API mit dem Inhaltstyp multipart/form-data (z.B. beim Hochladen von Dateien und Blobs auf den Server), sollten Sie nicht den Content-Type-Header explizit in der Anfrage setzen. Andernfalls kann der Browser den Content-Type-Header mit dem Begrenzungsausdruck, den er zur Abgrenzung von Formularfeldern im Anfrage-Body verwendet, nicht setzen.

Sie können auch eine File oder ein Blob direkt dem FormData-Objekt hinzufügen, wie folgt:

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

Beim Verwenden der append()-Methode ist es möglich, den dritten optionalen Parameter zu verwenden, um einen Dateinamen im Content-Disposition-Header zu übergeben, der an den Server gesendet wird. Wenn kein Dateiname angegeben ist (oder der Parameter nicht unterstützt wird), wird der Name "blob" verwendet.

Verwendung eines formdata-Ereignisses

Das formdata-Ereignis, das neuer als das FormData-Objekt ist, wird auf einem HTMLFormElement ausgelöst, nachdem die Eintragsliste, die die Daten des Formulars repräsentiert, erstellt wurde. Dies geschieht, wenn das Formular übermittelt wird, kann aber auch durch den Aufruf eines FormData()-Konstruktors ausgelöst werden.

Dies ermöglicht es, ein FormData-Objekt schnell als Reaktion auf das Auslösen eines formdata-Ereignisses zu erhalten, anstatt es selbst zusammenstellen zu müssen.

Zum Beispiel können wir im JavaScript auf ein Formular referenzieren:

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

In unserem submit-Ereignishandler verwenden wir preventDefault, um die Standardformularübermittlung zu stoppen, und rufen dann einen FormData()-Konstruktor auf, um das formdata-Ereignis auszulösen:

js
formElem.addEventListener("submit", (e) => {
  // on form submission, prevent default
  e.preventDefault();

  // construct a FormData object, which fires the formdata event
  new FormData(formElem);
});

Wenn das formdata-Ereignis ausgelöst wird, können wir auf das FormData-Objekt mit FormDataEvent.formData zugreifen, und dann damit machen, was wir möchten (unten senden wir es mit XMLHttpRequest an den Server).

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,
  });
});

Stolpersteine

Das FormData-Objekt enthält keine Daten aus Feldern, die deaktiviert sind, oder aus deaktivierten Fieldsets.

Siehe auch