Skip to main content

Form Data Middleware

Form body parsing middleware that parses incoming FormData and exposes it via context.get(FormData).

Installation

npm i remix

Function

formData()

Creates middleware that parses FormData from the request body and populates request context. Signature:
function formData(options?: FormDataOptions): Middleware
Parameters:
  • options - Optional form data parsing settings
Returns: A middleware function that parses form data.

Options

FormDataOptions

interface FormDataOptions extends ParseFormDataOptions {
  suppressErrors?: boolean
  uploadHandler?: FileUploadHandler
}

suppressErrors

Set true to suppress parse errors. When enabled, invalid form data will result in an empty FormData object instead of throwing an error.
  • Type: boolean
  • Default: false

uploadHandler

A function that handles file uploads. It receives a FileUpload object and may return any value that is a valid FormData value. Default is undefined, which means file uploads are stored in memory.
  • Type: FileUploadHandler
  • Default: undefined
Signature:
type FileUploadHandler = (upload: FileUpload) => Promise<File | string | null>

Basic Usage

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

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

router.post('/users', async (context) => {
  let formData = context.get(FormData)
  let name = formData.get('name')
  let email = formData.get('email')

  return Response.json({ name, email })
})

File Uploads

Uploaded files are available in the parsed FormData object. For a single file field, use formData.get(name). For repeated file fields, use formData.getAll(name).
import { createRouter } from 'remix/fetch-router'
import { formData } from 'remix/form-data-middleware'

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

router.post('/upload', async (context) => {
  let formData = context.get(FormData)
  let avatar = formData.get('avatar')

  if (avatar instanceof File) {
    console.log('Uploaded file:', avatar.name, avatar.size, 'bytes')
  }

  return Response.json({ hasAvatar: avatar instanceof File })
})

Custom Upload Handler

You can use a custom upload handler to customize how file uploads are handled. The return value of the upload handler will be used as the value of the form field in the FormData object.
import { formData } from 'remix/form-data-middleware'
import { writeFile } from 'node:fs/promises'

let router = createRouter({
  middleware: [
    formData({
      async uploadHandler(upload) {
        // Save to disk and return path
        let path = `./uploads/${upload.name}`
        await writeFile(path, Buffer.from(await upload.arrayBuffer()))
        return path
      },
    }),
  ],
})

router.post('/upload', async (context) => {
  let formData = context.get(FormData)
  let avatarPath = formData.get('avatar') // Returns the file path string
  return Response.json({ avatarPath })
})

Suppress Errors

Some requests may contain invalid form data that cannot be parsed. You can suppress parse errors by setting suppressErrors to true.
let router = createRouter({
  middleware: [
    formData({
      suppressErrors: true, // Invalid form data won't throw
    }),
  ],
})

Multiple File Upload

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

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

router.post('/upload-multiple', async (context) => {
  let formData = context.get(FormData)
  let images = formData.getAll('images') // Get all files with name="images"

  let files = images.filter((item): item is File => item instanceof File)

  return Response.json({
    count: files.length,
    sizes: files.map(f => f.size),
  })
})

Types

FileUpload

interface FileUpload {
  name: string
  type: string
  arrayBuffer(): Promise<ArrayBuffer>
}

FormDataParseError

Thrown when form data parsing fails (unless suppressErrors is true).
import { FormDataParseError } from 'remix/form-data-middleware'

try {
  // Parse form data
} catch (error) {
  if (error instanceof FormDataParseError) {
    console.error('Form data parsing failed:', error.message)
  }
}

Build docs developers (and LLMs) love