Verwenden von FormData-Objekten

Das FormData-Objekt ermöglicht es Ihnen, eine Reihe von Schlüssel/Wert-Paaren zusammenzustellen, die mit der Fetch oder XMLHttpRequest API gesendet werden sollen. Es ist hauptsächlich für die Verwendung beim Senden von Formulardaten gedacht, kann jedoch unabhängig von Formularen verwendet werden, um mit Schlüssel versehene Daten zu übertragen. Die übertragenen Daten haben dasselbe Format, das die Methode submit() des Formulars verwenden würde, wenn der Encoding-Typ 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 dann Felder durch Aufrufen der Methode append() hinzufügen, so:

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" enthalten beide eine Datei. Die Nummer, die dem Feld "accountNum" zugewiesen wird, wird sofort in einen String umgewandelt durch die Methode FormData.append() (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 namens "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 aus unveränderlichen, rohen Daten. Blobs repräsentieren Daten, die nicht unbedingt im JavaScript-eigenen Format vorliegen. Das File-Interface basiert auf Blob und erbt die Blob-Funktionalität und erweitert sie zur Unterstützung von Dateien auf dem Benutzer-System. Um ein Blob zu erstellen, können Sie 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, geben Sie dieses Formularelement beim Erstellen des FormData-Objekts an:

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

js
const formData = new FormData(someFormElement);

Zum Beispiel:

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, so:

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 Formulardaten vor dem Senden zu erweitern, um zusätzliche Informationen einzuschließen, die nicht unbedingt von Benutzern bearbeitet werden können.

Senden von Dateien mit einem FormData-Objekt

Sie können auch Dateien mit FormData senden. Fügen Sie ein <input>-Element des Typs file in Ihr <form> 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 folgendem Code 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 einen Verweis auf das Formular übergeben, wird die im Formular angegebene HTTP-Methodenanforderung gegenüber der in dem open()-Aufruf angegebenen Methode verwendet.

Warnung: Wenn Sie FormData verwenden, um POST-Anfragen mit XMLHttpRequest oder der Fetch API mit dem Inhaltstyp multipart/form-data einzureichen (z. B. beim Hochladen von Dateien und Blobs auf den Server), setzen Sie nicht explizit den Content-Type Header in der Anfrage. Andernfalls verhindert dies, dass der Browser den Content-Type-Header mit dem Grenzausdruck festlegt, den er zur Abgrenzung der Formularfelder im Anfragetext verwendet.

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

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

Bei Verwendung der append()-Methode ist es möglich, den dritten optionalen Parameter zu nutzen, um einen Dateinamen im Content-Disposition-Header zu übermitteln, 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, aktueller als das FormData-Objekt, wird auf einem HTMLFormElement-Objekt ausgelöst, nachdem die Eintragsliste, die die Formulardaten darstellt, erstellt wurde. Dies geschieht, wenn das Formular eingereicht wird, kann aber auch durch den Aufruf eines FormData()-Konstruktors ausgelöst werden.

Dies ermöglicht es, schnell ein FormData-Objekt als Antwort 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 verweisen:

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

In unserem submit-Ereignis-Handler verwenden wir preventDefault, um das standardmäßige Formulareinreichen 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 zugreifen, indem wir FormDataEvent.formData verwenden, und anschließend damit machen, was wir möchten (unten posten wir es an den Server mit 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,
  });
});

Stolpersteine

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

Siehe auch