Skip to content

File Upload

The File field handles single and multiple file uploads with drag-and-drop, image previews, validation, temporary upload support, and optional direct-to-storage uploads. Files use temporary uploads by default: they are sent to the server before the form is submitted, and the form submits an encrypted temporary upload token.

Basic Usage

php
use InertiaUI\Forms\Fields\File;

File::make('document');

The field starts empty. By default, selecting a file uploads it to the built-in temporary upload route immediately. The final form request receives an encrypted upload token.

Single-file fields submit one token or null. Multiple fields submit an ordered array of tokens, or null after every item is removed.

Accept and Image

Restrict which file types are accepted:

php
// Specific MIME types
File::make('document')->accept([
    'application/pdf',
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
]);

// Shorthand for images
File::make('avatar')->image();

The image() method sets the accept to image/* and adds the image validation rule. The accept() method adds a mimetypes validation rule.

Multiple Files

Allow uploading more than one file:

php
File::make('attachments')->multiple();

Max Files

Limit the number of files:

php
File::make('photos')
    ->multiple()
    ->maxFiles(5);

File Size

Set minimum and maximum file sizes in kilobytes:

php
File::make('upload')
    ->maxSize(5120)  // 5MB max
    ->minSize(10);   // 10KB min

These add max and min validation rules for the file.

Image Dimensions

Constrain image dimensions. These add Laravel's dimensions validation rule.

Exact Dimensions

php
File::make('icon')
    ->image()
    ->dimensions(width: 512, height: 512);

Min/Max Dimensions

php
File::make('banner')
    ->image()
    ->minDimensions(width: 800, height: 200)
    ->maxDimensions(width: 2000, height: 600);

You may mix width and height constraints:

php
File::make('photo')
    ->image()
    ->minDimensions(width: 400)
    ->maxDimensions(width: 2000, height: 2000);

Preview

Image previews are shown by default. Hide them:

php
File::make('document')->hidePreview();

// Or use the explicit method
File::make('document')->showPreview(false);

File Size Display

File sizes are hidden in uploaded item cards by default. Show them when the field needs that detail:

php
File::make('gallery')
    ->multiple()
    ->showFileSize();

Reorderable

Allow users to reorder uploaded files with move buttons or drag and drop (multiple mode):

php
File::make('gallery')
    ->multiple()
    ->reorderable();

Item Layout

Choose how the list of uploaded files is presented. This is presentation-only. It does not affect the upload path, validation, or how submitted values are serialized. It is distinct from the field-presentation layout() (stacked/inline/split), which arranges the field label and control.

List

list is the default layout. It renders full-width rows with preview, name, and actions.

Example
  • notebook.jpg

    notebook.jpg

    54.7 KB

  • camera-lens.png

    camera-lens.png

    722.7 KB

  • travel-bag.jpg

    travel-bag.jpg

    132.8 KB

php
File::make('gallery')
    ->multiple()
    ->maxFiles(3)
    ->showFileSize()
    ->reorderable();

Compact

compact uses tighter rows with reduced padding. It keeps the same mechanics as list.

Example
  • notebook.jpg

    notebook.jpg

    54.7 KB

  • camera-lens.png

    camera-lens.png

    722.7 KB

  • travel-bag.jpg

    travel-bag.jpg

    132.8 KB

php
File::make('gallery')
    ->multiple()
    ->maxFiles(3)
    ->showFileSize()
    ->reorderable()
    ->itemLayout('compact');

Grid

grid renders a thumbnail/item grid suited to multiple image fields.

Example
  • notebook.jpg

    notebook.jpg

    54.7 KB

  • camera-lens.png

    camera-lens.png

    722.7 KB

  • travel-bag.jpg

    travel-bag.jpg

    132.8 KB

php
File::make('gallery')
    ->multiple()
    ->maxFiles(3)
    ->showFileSize()
    ->reorderable()
    ->itemLayout('grid')
    ->itemColumns(3);

Use itemColumns(2) or itemColumns(3) when a grid should keep a stable card width instead of stretching the remaining items across the whole row. The value is the maximum column target. The grid still drops to fewer columns when the container is too narrow for that target.

All actions (remove, retry, move up/down, browse/dropzone) stay keyboard reachable in every layout, and reordering still works in grid through the existing move buttons. There is no drag-only dependency. Invalid values throw an InvalidArgumentException.

Upload Paths

The default upload path stores selected files temporarily before the form is submitted. The final form request receives encrypted temporary upload tokens in the current UI order.

Use File Uploads for upload transport setup, including storeWithForm(), custom temporary upload URLs, named upload routes, chunked(), directToStorage(), direct upload disks, multipart tuning, upload validators, and token validation.

Store With The Form

storeWithForm() keeps newly selected files as native multipart File values until the final form request. This is useful for small create forms that do not need existing-file preservation:

Example

The selected file stays local until the form is submitted.

php
File::make('avatar')
    ->label('Avatar')
    ->help('The selected file stays local until the form is submitted.')
    ->image()
    ->storeWithForm();

Storage Disk

Set disk() when a bound model stores existing files on a disk other than public. The disk is used to turn saved paths into browser previews for edit forms:

php
File::make('document')->disk('s3');

Direct-to-storage upload disks and multipart tuning are covered in File Uploads.

Spatie Media Library

For models that use Spatie Media Library, associate the upload with a media collection:

php
File::make('photos')
    ->multiple()
    ->mediaCollection('product-images');

A bound model automatically loads existing media from the collection as the field's value.

Product Photo Upload

php
File::make('photos')
    ->label('Product Photos')
    ->help('Upload up to 8 images, max 5MB each')
    ->image()
    ->multiple()
    ->maxFiles(8)
    ->maxSize(5120)
    ->minDimensions(width: 400, height: 400)
    ->maxDimensions(width: 4000, height: 4000)
    ->reorderable()
    ->mediaCollection('product-images')
    ->required();

Shared Field APIs

File upload fields also use Form Class for labels and help text, Model Binding for default() and bound values, Validation for rules and precognition, Conditional Visibility, Authorization, and Styling for classes, layout, and part classes.

Using the Component Directly

You may render FileUpload outside the generated <Form> with local state. Upload transports use the serialized props described in File Uploads.

vue
<script setup lang="ts">
import { shallowRef } from 'vue'
import { FileUpload, type FileUploadValue } from '@inertiaui/form-vue/components'
import type { ExistingFile } from '@inertiaui/form-vue'

const gallery = shallowRef<FileUploadValue>(null)

const existingGallery: ExistingFile[] = [
    {
        key: 'gallery/product-cover.jpg',
        name: 'Product cover.jpg',
        size: 428000,
        mimeType: 'image/jpeg',
    },
]

const fileParts = {
    item: 'bg-white',
    preview: 'ring-1 ring-zinc-200',
    feedback: 'text-sm',
}
</script>

<template>
    <FileUpload
        v-model="gallery"
        id="gallery"
        name="gallery"
        label="Gallery"
        help="Upload up to five product images."
        :accept="['image/*']"
        :multiple="true"
        :max-files="5"
        :max-size="2048"
        :show-preview="true"
        :show-file-size="true"
        :existing-files="existingGallery"
        :reorderable="true"
        item-layout="grid"
        :item-columns="3"
        :store-with-form="true"
        wrapper-class="max-w-2xl"
        control-class="bg-white"
        :part-classes="fileParts"
    />
</template>
tsx
import { useState } from 'react'
import { FileUpload, type FileUploadValue } from '@inertiaui/form-react/components'
import type { ExistingFile } from '@inertiaui/form-react'

const existingGallery: ExistingFile[] = [
    {
        key: 'gallery/product-cover.jpg',
        name: 'Product cover.jpg',
        size: 428000,
        mimeType: 'image/jpeg',
    },
]

const fileParts = {
    item: 'bg-white',
    preview: 'ring-1 ring-zinc-200',
    progress: 'h-2',
    feedback: 'text-sm',
}

export default function GalleryUpload() {
    const [gallery, setGallery] = useState<FileUploadValue>(null)

    return (
        <FileUpload
            value={gallery}
            onValueChange={setGallery}
            id="gallery"
            name="gallery"
            label="Gallery"
            help="Upload up to five product images."
            accept={['image/*']}
            multiple
            maxFiles={5}
            maxSize={2048}
            showPreview
            showFileSize
            existingFiles={existingGallery}
            reorderable
            itemLayout="grid"
            itemColumns={3}
            storeWithForm
            wrapperClass="max-w-2xl"
            controlClass="bg-white"
            partClasses={fileParts}
        />
    )
}

Vue uses v-model. React uses controlled value plus onValueChange. FileUpload is a composite control and does not forward arbitrary native attributes or listeners to one inner element. See Native Attributes And Events.