Start · Sprachen · JavaScript · Referenz · Response.formData()

Response.formData()

Methode

Liest den Body-Stream einer <code>Response</code> vollständig aus und gibt ein Promise zurück, das mit einem <code>FormData</code>-Objekt erfüllt wird.

seit JavaScript Baseline: alle modernen Browser (seit 2017), Node. Kategorie: webapi

Signatur

Response.prototype.formData()

Beschreibung

Die Methode formData() des Response-Interfaces liest den Body-Stream einer Antwort bis zum Ende und wertet ihn als Formulardaten aus. Das Ergebnis ist ein FormData-Objekt, dessen Schlüssel-Wert-Paare man mit get(), getAll(), has() oder per Iteration abfragen kann.

Ausgewertet werden zwei Formate, erkannt am Content-Type-Header: multipart/form-data (inklusive Dateien, die als File-Objekte ankommen) und application/x-www-form-urlencoded. Bei jedem anderen oder fehlenden Content-Type wird das Promise mit einem TypeError abgelehnt.

In der Praxis braucht man die Methode vor allem in Service Workern und serverseitigen Laufzeitumgebungen (Node.js, Deno, Cloudflare Workers) – dort meist in der Variante Request.formData(), um abgeschickte Formulare auszuwerten. Auf der Response-Seite ist sie nützlich, wenn ein Server Formulardaten zurückgibt, oder um einen FormData-Body über new Response(formData) zu serialisieren und wieder einzulesen.

Wie alle Body-Methoden (json(), text(), blob() …) kann formData() nur einmal pro Response aufgerufen werden, weil der Stream dabei verbraucht wird.

Rückgabewert

Typ
Promise<FormData>
Beschreibung
Ein Promise, das mit einem FormData-Objekt erfüllt wird. Es wird mit einem TypeError abgelehnt, wenn der Body schon gelesen wurde, der Content-Type nicht passt oder der Inhalt nicht ausgewertet werden kann. Wurde der Abruf abgebrochen, lautet der Fehler AbortError.

Beispiele

Hin und zurück: FormData als Response serialisieren und wieder einlesen

const fd = new FormData();
fd.append('name', 'Anna');
fd.append('tags', 'js');
fd.append('tags', 'web');

// new Response(FormData) setzt automatisch multipart/form-data mit Boundary
const response = new Response(fd);
const parsed = await response.formData();

console.log(parsed.get('name'));
console.log(parsed.getAll('tags'));
Anna [ 'js', 'web' ]

URL-kodierten Body auswerten

const response = new Response('user=max&rolle=admin', {
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});

const data = await response.formData();
for (const [key, value] of data) {
  console.log(`${key}: ${value}`);
}
user: max rolle: admin

Formulardaten im Service Worker abfangen (Request-Variante)

// sw.js
self.addEventListener('fetch', (event) => {
  const { request } = event;
  if (request.method === 'POST' && new URL(request.url).pathname === '/kontakt') {
    event.respondWith((async () => {
      const data = await request.formData();
      const email = data.get('email');
      return new Response(`Danke, ${email}!`, {
        headers: { 'Content-Type': 'text/plain; charset=utf-8' }
      });
    })());
  }
});

Fehler bei falschem Content-Type und bereits gelesenem Body abfangen

const response = await fetch('/api/daten'); // liefert z. B. JSON

try {
  const data = await response.formData();
  console.log([...data.keys()]);
} catch (err) {
  console.error(err.name, '-', err.message);
}

console.log(response.bodyUsed);
TypeError - (browserspezifische Meldung, z. B. "Could not parse content as FormData.") true

// Wichtig · Fallstricke

  • Nur einmal lesbar: Nach dem Aufruf ist response.bodyUsed gleich true; ein zweiter Aufruf einer Body-Methode löst einen TypeError aus. Wer den Body mehrfach braucht, ruft vorher response.clone() auf.
  • Content-Type ist entscheidend: Ohne multipart/form-data (mit gültigem boundary) oder application/x-www-form-urlencoded wird das Promise abgelehnt. Wer den Header bei multipart von Hand setzt, vergisst leicht die Boundary. Bei new Response(formData) also keinen eigenen Content-Type angeben.
  • Speicher: Der gesamte Body wird in den Speicher geladen, auch hochgeladene Dateien. Für große Uploads ist das Streamen über response.body besser.
  • Sicherheit: Werte aus FormData sind Benutzereingaben. Vor dem Einfügen ins DOM (innerHTML) oder in Datenbankabfragen müssen sie geprüft bzw. maskiert werden. Dateinamen und MIME-Typen von File-Einträgen sind vom Client vorgegeben und nicht vertrauenswürdig.
  • Kompatibilität: Wird von allen modernen Browsern unterstützt. In Node.js steht die Methode ab Version 18 über das eingebaute fetch (undici) zur Verfügung. Ältere Chromium-Versionen konnten multipart-Antworten im Fenster-Kontext nicht auswerten, nur in Service Workern.