---
type: "package"
title: "remix/middleware/form-data/future"
---

# remix/middleware/form-data/future

Form body parsing middleware for Remix. It parses incoming [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) and exposes it via `context.formData` (or `context.get(FormData)`).

## Features

- **Request Form Parsing** - Parses request body form data once per request
- **File Access** - Uploaded files are available from `context.formData` (or `context.get(FormData)`)
- **Custom Upload Handling** - Supports pluggable upload handlers for file processing
- **Error Control** - Optional suppression for malformed form data

## Installation

```sh
npm i remix
```

## Usage

Use the `formData()` middleware at the router level to parse `FormData` from the request body and make it available as `context.formData` (or `context.get(FormData)`).

When `formData()` runs successfully it always provides a `FormData` value. Requests that do not contain a form body, including `GET` and `HEAD` requests, receive an empty `FormData`.

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)`.

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

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

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

  // Handle file uploads
  let avatar = formData.get('avatar')

  return Response.json({ name, email, hasAvatar: avatar instanceof File })
})
```

Use `context.formData` (or `context.get(FormData)`).

### Custom File 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.

`upload.name` and the names of uploaded files in `context.formData` are untrusted client input, not sanitized filesystem paths. Generate storage names in your application instead of using these names directly or joining them to an upload directory; see [Filename Safety](https://github.com/remix-run/remix/tree/main/packages/headers#filename-safety).

```ts
import { formData } from 'remix/middleware/form-data'
import { createRouter } from 'remix/router'
import { writeFile } from 'node:fs/promises'

let router = createRouter({
  middleware: [
    formData({
      async uploadHandler(upload) {
        // Save under an application-generated name in an existing upload directory
        let path = `./uploads/${crypto.randomUUID()}`
        await writeFile(path, new Uint8Array(await upload.arrayBuffer()), { flag: 'wx' })
        return path
      },
    }),
  ],
})
```

### Limit Multipart Growth

`formData()` forwards multipart limit options to `parseFormData()`, so you can cap uploads with `maxHeaderSize`, `maxFiles`, `maxFileSize`, `maxParts`, and `maxTotalSize`.

```ts
let router = createRouter({
  middleware: [
    formData({
      maxFiles: 5,
      maxFileSize: 10 * 1024 * 1024,
      maxParts: 25,
      maxTotalSize: 12 * 1024 * 1024,
    }),
  ],
})
```

### Suppress Parse Errors

Some requests may contain invalid form data that cannot be parsed. You can suppress those malformed-body parse errors by setting `suppressErrors` to `true`. In these cases, `context.formData` will be an empty `FormData` object. Multipart limit violations from `maxHeaderSize`, `maxFiles`, `maxFileSize`, `maxParts`, or `maxTotalSize` are never suppressed.

```ts
let router = createRouter({
  middleware: [
    formData({
      suppressErrors: true, // Invalid form data won't throw
    }),
  ],
})
```

## Future API

**Future APIs are not stable.** The `remix/middleware/form-data/future` entrypoint may change in any release, but it is a good indication of where this package will land in its next major release.

`formData()` from `remix/middleware/form-data/future` parses requests with [`remix/form-data-parser/future`](https://github.com/remix-run/remix/tree/main/packages/form-data-parser#future-api), so file uploads stream to your `uploadHandler` instead of being buffered in memory. Read each upload inside the handler; uploads the handler returns unread are read into a regular `File`.

```ts
import { formData } from 'remix/middleware/form-data/future'

let router = createRouter({
  middleware: [
    formData({
      async uploadHandler(upload) {
        let storageKey = crypto.randomUUID()
        await fileStorage.set(storageKey, upload)
        return storageKey
      },
    }),
  ],
})
```

## Related Packages

- [`fetch-router`](https://github.com/remix-run/remix/tree/main/packages/fetch-router) - Router for the web Fetch API
- [`form-data-parser`](https://github.com/remix-run/remix/tree/main/packages/form-data-parser) - The underlying form data parser

## License

See [LICENSE](https://github.com/remix-run/remix/blob/main/LICENSE)

