obsidian/wiki/payloadcms/fields-upload.md
2026-05-15 15:41:45 +01:00

100 lines
3.7 KiB
Markdown

---
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: '<id>' }` (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