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

Request.formData()

Methode

Liest den Körper eines <code>Request</code> vollständig ein 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

Request.prototype.formData()

Beschreibung

formData() gehört zum Body-Mixin, das Request und Response gemeinsam haben. Die Methode liest den Datenstrom des Anfragekörpers bis zum Ende und wandelt ihn in ein FormData-Objekt um. Unterstützt werden die Inhaltstypen multipart/form-data und application/x-www-form-urlencoded. Welches Format vorliegt, erkennt die Methode am Content-Type-Header der Anfrage.

Im Browser braucht man sie selten. Richtig nützlich ist sie serverseitig und in Service Workern: in einem fetch-Event-Handler, in Edge-Funktionen (Cloudflare Workers, Deno, Vercel), in Route-Handlern von Next.js, Remix oder SvelteKit sowie in Node.js ab Version 18 mit der eingebauten Fetch-API. Dort lassen sich abgeschickte HTML-Formulare, auch mit Datei-Uploads, ohne zusätzliche Bibliothek auswerten.

Der Körper eines Requests lässt sich nur einmal lesen. Nach dem Aufruf ist request.bodyUsed auf true gesetzt. Jeder weitere Leseversuch mit json(), text() oder erneut formData() scheitert mit einem TypeError. Wer den Körper mehrfach braucht, erstellt vorher mit request.clone() eine Kopie.

Rückgabewert

Typ
Promise<FormData>
Beschreibung
Ein Promise, das mit einem FormData-Objekt erfüllt wird. Hochgeladene Dateien erscheinen darin als File-Objekte, alle anderen Felder als Strings. Das Promise wird mit einem TypeError abgelehnt, wenn der Körper schon gelesen wurde, der Content-Type fehlt oder nicht passt oder die Daten nicht geparst werden können.

Beispiele

Request mit FormData erzeugen und wieder auslesen

const fd = new FormData();
fd.append('name', 'Anna');
fd.append('sprache', 'de');

const request = new Request('https://example.com/api', {
  method: 'POST',
  body: fd // Content-Type multipart/form-data wird automatisch gesetzt
});

const daten = await request.formData();
console.log(daten.get('name'));
console.log([...daten.keys()]);
Anna ["name", "sprache"]

URL-kodierte Daten parsen

const request = new Request('https://example.com/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: 'benutzer=max&passwort=geheim123'
});

const form = await request.formData();
const { benutzer } = Object.fromEntries(form);
console.log(benutzer);
max

Datei-Upload in einem Route-Handler (Web-Standard, z. B. Next.js / Deno / Workers)

export const POST = async (request) => {
  let form;
  try {
    form = await request.formData();
  } catch {
    return new Response('Ungültiger Formularkörper', { status: 400 });
  }

  const titel = form.get('titel') ?? '';
  const datei = form.get('datei');

  if (!(datei instanceof File)) {
    return new Response('Keine Datei übermittelt', { status: 400 });
  }

  const bytes = await datei.arrayBuffer();
  return Response.json({ titel, dateiname: datei.name, groesse: bytes.byteLength });
};
{"titel":"Urlaub","dateiname":"foto.jpg","groesse":204800}

Service Worker: Körper klonen, um ihn doppelt zu nutzen

self.addEventListener('fetch', (event) => {
  const { request } = event;
  if (request.method !== 'POST' || !request.url.endsWith('/kontakt')) return;

  event.respondWith((async () => {
    // Kopie für die Auswertung, das Original geht ans Netzwerk
    const form = await request.clone().formData();
    console.log('E-Mail:', form.get('email'));
    return fetch(request);
  })());
});
E-Mail: nutzer@example.com

// Wichtig · Fallstricke

  • Einmal lesbar: Nach dem ersten Aufruf ist bodyUsed === true. Ein zweiter Leseversuch wirft einen TypeError. Deshalb vorher request.clone() verwenden.
  • Content-Type ist Pflicht: Fehlt der Header oder hat er einen anderen Wert, etwa application/json, wird das Promise abgelehnt. Bei multipart/form-data muss außerdem der Parameter boundary stimmen. Setzen Sie diesen Header nie von Hand, wenn der Körper ein FormData-Objekt ist. Den Header setzt der Browser bzw. die Laufzeit automatisch, samt korrekter Boundary.
  • Speicher: Der gesamte Körper wird in den Speicher geladen, auch große Dateien. Bei großen Uploads besser direkt mit request.body als Stream arbeiten oder eine Größenobergrenze prüfen, z. B. über den Header Content-Length.
  • Sicherheit: Formularwerte sind Eingaben des Nutzers. Prüfen und validieren Sie Typ, Länge und Dateityp (file.type lässt sich fälschen), bevor Sie die Werte speichern oder als HTML ausgeben (Gefahr von XSS).
  • Kompatibilität: Unterstützt von allen modernen Browsern sowie Node.js 18+ (undici), Deno, Bun und Cloudflare Workers. Ältere Node-Versionen ohne eingebautes fetch kennen die Methode nicht.
  • form.get() gibt null zurück, wenn das Feld fehlt. Bei mehrfach vorkommenden Feldern liefert erst getAll() alle Werte.