Skip to content

form-data-middleware Overview

The formData middleware parses HTML form submissions into a standard FormData object that your handlers can read. It supports both URL-encoded forms and multipart forms (which include file uploads).

What is Form Data Parsing?

When a user submits an HTML form, the browser encodes the form fields into the request body. The server needs to parse (decode) that body to access the submitted values. There are two encoding formats:

URL-Encoded (application/x-www-form-urlencoded)

This is the default encoding for HTML forms. Field names and values are joined with = and separated by &:

title=Hello+World&body=My+first+post

This format works well for text fields but cannot handle file uploads.

Multipart (multipart/form-data)

When a form includes file uploads (<input type="file">), the browser uses multipart encoding. Each field is sent as a separate "part" with its own headers:

------boundary
Content-Disposition: form-data; name="title"

Hello World
------boundary
Content-Disposition: form-data; name="avatar"; filename="photo.jpg"
Content-Type: image/jpeg

[binary file data]
------boundary--

The formData middleware handles both formats automatically -- you do not need to check which one was used.

Key Features

Standard FormData API

The middleware returns a standard FormData object, the same API available in browsers. If you know how to use FormData on the client, you already know how to use it on the server:

ts
let data = context.get(FormData)
let title = data.get('title')        // string | null
let tags = data.getAll('tags')        // string[]
let avatar = data.get('avatar')       // File | string | null

File Upload Handling

Uploaded files are available as File objects. The default handler stores them in memory, but you can provide a custom upload handler to store files on disk, S3, or any other storage backend.

Size Limits

Protect your server from oversized uploads with configurable limits for file size, number of files, and total number of form parts.

Quick Example

ts
import { createRouter } from 'remix/fetch-router'
import { formData, FormData } from 'remix/form-data-middleware'

let router = createRouter({
  middleware: [
    formData(),
  ],
})

router.post(routes.contact, async ({ context }) => {
  let data = context.get(FormData)
  let name = data.get('name')
  let email = data.get('email')

  await sendEmail({ to: 'support@example.com', subject: `Message from ${name}`, from: email })
  return redirect('/contact/thanks')
})

Next Steps

Released under the MIT License.