--- title: "Upload Field" aliases: [upload-field, payload-upload, media-field] tags: [payloadcms, fields, upload, media, relationships] sources: [raw/fields__upload.md] created: 2026-05-15 updated: 2026-05-15 --- The Upload Field references a document from an upload-enabled Collection, rendered as a thumbnail in the Admin Panel. It is a typed relationship to a media/file Collection. ## Basic Config ```ts import type { Field } from 'payload' export const MyUploadField: Field = { type: 'upload', name: 'backgroundImage', // required relationTo: 'media', // required — must be an upload-enabled collection required: true, } ``` > **Prerequisite:** target Collection must have `upload: true` (or an upload config object) in its [[wiki/payloadcms/collection-config|Collection Config]]. ## Key Config Options | Option | Description | |--------|-------------| | `relationTo` | Single slug or array of slugs (polymorphic). **Must** point to upload collection(s). | | `hasMany` | `true` → accepts multiple uploads | | `minRows` / `maxRows` | Validation bounds when `hasMany: true` | | `filterOptions` | `Where` query or function — limits selectable files in UI and validates on save | | `displayPreview` | Override Collection-level preview thumbnail setting | | `maxDepth` | Max auto-populate depth for related document | | `unique` | DB-level unique index | | `localized` | Per-locale upload reference | | `virtual` | Skip DB storage or link to a relationship path | | `saveToJWT` | Include in JWT if field is top-level in an auth Collection | ## Filtering Upload Options Restrict selectable files dynamically: ```ts // Static Where query — only images const imageField = { name: 'image', type: 'upload', relationTo: 'media', filterOptions: { mimeType: { contains: 'image' }, }, } ``` As a function (receives `{ relationTo, data, siblingData, id, user, req }`): ```ts filterOptions: ({ user }) => { if (user.role === 'admin') return true // no filter return { uploadedBy: { equals: user.id } } } ``` > **Gotcha:** If you combine `filterOptions` with a custom `validate` function, call the default upload field validator from `payload/shared` inside your function — otherwise `filterOptions` won't be validated by the API. ## Polymorphic Uploads Reference multiple upload collections: ```ts { name: 'media', type: 'upload', relationTo: ['images', 'documents', 'videos'], hasMany: true, // optional — allow multiple selections } ``` When polymorphic, the stored value is `{ relationTo: 'images', value: '' }` (same shape as polymorphic [[wiki/payloadcms/fields-relationship|Relationship Field]]). ## Bi-directional Relationships The upload field alone is a one-way reference. To view from the media document which other documents use it, add a [[wiki/payloadcms/fields-join|Join Field]] on the upload Collection pointing back. ## Key Takeaways - `relationTo` is **required** and must point to an upload-enabled Collection — a plain Collection won't work - Use `hasMany: true` for galleries / multi-file selectors; pair with `minRows`/`maxRows` for validation - `filterOptions` filters both UI picker and API validation — mix with `where` queries from [[wiki/payloadcms/queries|Queries]] - Combining `filterOptions` + custom `validate` requires calling the built-in validator from `payload/shared` - Polymorphic: pass an array to `relationTo` — stored value gets a `{ relationTo, value }` wrapper - For reverse lookup (where is this media used?), use [[wiki/payloadcms/fields-join|Join Field]] on the media Collection - `displayPreview` can be overridden per-field, independent of the Collection setting ## Sources - `raw/fields__upload.md` — Payload CMS official docs, Upload Field