Skip to content

Form Data Parser Overview

The built-in request.formData() method buffers the entire request body in memory before returning. For requests with large file uploads, this can exhaust server memory.

The form-data-parser package provides parseFormData, a drop-in replacement that streams file uploads instead of buffering them. It returns a standard FormData object where file fields are represented as FileUpload instances -- objects that give you access to the file's name, type, size, and a readable stream of its content.

When to Use This Package

Use form-data-parser whenever your route handles form submissions that may include file uploads. It is the recommended way to handle file uploads in Remix V3. For lower-level control over individual multipart parts, see multipart-parser.

Quick Example

ts
import { parseFormData, FileUpload } from 'remix/form-data-parser'

export async function action({ request }: { request: Request }) {
  let formData = await parseFormData(request)

  let title = formData.get('title') as string
  let avatar = formData.get('avatar') as FileUpload

  console.log(avatar.name) // 'photo.jpg'
  console.log(avatar.type) // 'image/jpeg'
  console.log(avatar.size) // 1048576
}

Key Concepts

  • FileUpload -- A class representing an uploaded file. It has name, type, size, and stream() properties, similar to the standard File class but backed by streaming data.
  • Upload handler -- An optional callback function that receives each FileUpload and decides what to do with it (save to disk, upload to S3, etc.). When no handler is provided, files are buffered in memory.
  • Drop-in replacement -- parseFormData returns a standard FormData object, so existing code that reads formData.get('field') continues to work.

With and Without an Upload Handler

Without a handler, files are buffered in memory (suitable for small files):

ts
let formData = await parseFormData(request)
let file = formData.get('document') as FileUpload

With a handler, files are streamed to your chosen destination:

ts
let formData = await parseFormData(request, {}, async (fileUpload) => {
  await storage.set(fileUpload.name, fileUpload)
  return fileUpload.name // The value placed in FormData
})

Released under the MIT License.