Reference

Configuration and commands

Upload configuration, opt-in routes, publish tags, Artisan commands, and operational security.

The service provider is discovered by Laravel. It always merges package configuration and registers macros and commands, but it never registers upload routes automatically.

Publish configuration

Publish config/inertia-forms.php only when the defaults need to change:

php artisan vendor:publish --tag=inertia-forms-config

The aliases inertify-form-config and inertify-form publish the same file.

Configuration reference

All keys live below inertia-forms.

KeyDefaultUnitPurpose
file_uploads.route_prefix/_inertia-formsURL prefix used when upload routes are registered.
file_uploads.route_nameinertia-forms.Route-name prefix. A trailing dot is normalized automatically.
file_uploads.middleware['web', 'auth']Middleware applied to the complete upload route group.
file_uploads.temporary_uploads.disk''Laravel filesystem disk for temporary and chunked content. Empty uses an isolated local directory at storage/inertia-forms-temporary-uploads.
file_uploads.temporary_uploads.lifetime3600secondsToken lifetime and the normal temporary cleanup age.
file_uploads.temporary_uploads.max_size10240KiBMaximum normal temporary upload size before field-specific constraints.
file_uploads.temporary_uploads.chunked.size5242880bytesDefault client chunk size.
file_uploads.temporary_uploads.chunked.max_size2097152KiBMaximum completed chunked upload size.
file_uploads.direct_to_storage.disk''Default filesystem disk for direct uploads. Empty requires a disk on each direct File field.
file_uploads.direct_to_storage.url_lifetime900secondsLifetime for a direct-upload session or signed upload URL.
file_uploads.direct_to_storage.part_size16777216bytesMultipart part size. S3 requires every non-final part to be at least 5 MiB.
file_uploads.direct_to_storage.multipart_threshold104857600bytesFiles larger than this use multipart direct upload.
file_uploads.direct_to_storage.max_size5242880KiBMaximum direct upload size before field-specific constraints.
authorization.throw_on_unauthorizedfalseThrow during serialization instead of returning an empty form resource. Validation always throws for an unauthorized form.

Field methods such as maxSize(), chunked($bytes), directToStorage($disk), partSize(), and multipartThreshold() override the corresponding serialized transport settings for that field.

File validation sizes follow Laravel's file-rule convention and are expressed in KiB. Chunk and multipart transport sizes are bytes.

Example production configuration

return [
    'file_uploads' => [
        'route_prefix' => '/_inertia-forms',
        'route_name' => 'inertia-forms.',
        'middleware' => ['web', 'auth', 'throttle:uploads'],

        'temporary_uploads' => [
            'disk' => 'private',
            'lifetime' => 3600,
            'max_size' => 10 * 1024,
            'chunked' => [
                'size' => 5 * 1024 * 1024,
                'max_size' => 2 * 1024 * 1024,
            ],
        ],

        'direct_to_storage' => [
            'disk' => 's3',
            'url_lifetime' => 900,
            'part_size' => 16 * 1024 * 1024,
            'multipart_threshold' => 100 * 1024 * 1024,
            'max_size' => 5 * 1024 * 1024,
        ],
    ],

    'authorization' => [
        'throw_on_unauthorized' => true,
    ],
];

Choose disks and limits for the host application. The example values are not a substitute for application-specific storage, cost, retention, or abuse controls.

Upload routes

Register the endpoints explicitly in an application route file:

use Illuminate\Support\Facades\Route;

Route::inertiaFormUploads();

Override the group settings with named arguments:

Route::inertiaFormUploads(
    prefix: '/form-assets',
    middleware: ['web', 'auth', 'verified', 'throttle:uploads'],
    name: 'form-assets',
);

For a route-name override, point fields at the same name prefix:

File::make('avatar')->uploadRoutes('form-assets');

Registered endpoints

Paths below are relative to the configured prefix. Names below are relative to the configured name prefix.

VerbPathRoute name suffixPurpose
POSTfile-uploadfile-upload.storeStore a temporary upload.
DELETEfile-uploadfile-upload.destroyRemove an unused upload token.
POSTfile-upload/chunked/startfile-upload.chunked.startCreate a resumable chunk session.
GETfile-upload/chunked/statusfile-upload.chunked.statusRead the accepted byte offset.
POSTfile-upload/chunked/chunkfile-upload.chunked.appendAppend the next chunk.
POSTfile-upload/chunked/completefile-upload.chunked.completeValidate and finalize chunked content.
DELETEfile-upload/chunked/abortfile-upload.chunked.abortAbort a chunk session.
POSTfile-upload/direct/startfile-upload.direct.startCreate a direct or multipart session.
PUTfile-upload/direct/objectfile-upload.direct.objectLocal-disk direct-upload fallback.
POSTfile-upload/direct/partfile-upload.direct.partSign an S3 multipart part or upload a local fallback part.
GETfile-upload/direct/statusfile-upload.direct.statusRead direct-upload progress.
POSTfile-upload/direct/completefile-upload.direct.completeFinalize direct content and return a submission token.
DELETEfile-upload/direct/abortfile-upload.direct.abortAbort a direct session.

storeWithForm() does not need package upload routes. A complete custom upload descriptor can also use application-owned endpoints.

Route security

Upload endpoints allocate storage. Keep authentication in place and add application authorization, tenant scope, CSRF protection, and rate limiting appropriate to the deployment. Replacing the default middleware with an empty list exposes every registered upload endpoint.

The package encrypts and expires upload tokens, restricts direct uploads to the signed disk profile, validates declared sizes, and rejects malformed, expired, purpose-mismatched, disk-mismatched, and rule-profile-mismatched tokens. These protections complement rather than replace application access control.

File methods such as image(), accept(), minSize(), maxSize(), and dimensions() become an encrypted validation profile for package-managed uploads. To require a profile even without those constraints, use:

File::make('document')->requireValidatedUploads();

Add application-specific content checks with a container-resolved validator class:

use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Inertify\Form\Contracts\ValidatesFileUploads;
use Inertify\Form\Uploads\TemporaryUpload;
use Inertify\Form\Uploads\UploadRules;

final class ScanDocumentUpload implements ValidatesFileUploads
{
    public function validate(
        TemporaryUpload $upload,
        UploadedFile $file,
        UploadRules $rules,
        Request $request,
    ): void {
        // Run the application's malware/content policy or throw.
    }
}

File::make('document')->validateUploadsUsing(ScanDocumentUpload::class);

Artisan commands

Generate a form

php artisan make:form ProfileForm

The generator creates App\Forms\ProfileForm by default with an empty fields() method.

Clean expired uploads

php artisan form:cleanup-uploads

Override the normal temporary lifetime for one run:

php artisan form:cleanup-uploads --lifetime=7200

--lifetime is a non-negative number of seconds. Cleanup:

  • scans only package-owned upload directories on the configured temporary and direct disks;
  • deletes expired temporary and chunked content;
  • aborts expired pending S3 multipart sessions before deleting their metadata;
  • retains completed direct uploads for the submission-token lifetime;
  • continues after individual failures and returns a failing exit code when any operation remains retriable.

Schedule it in the host application:

use Illuminate\Support\Facades\Schedule;

Schedule::command('form:cleanup-uploads')->hourly();

The cleanup command is operational maintenance, not an upload authorization control. Run it often enough for the selected storage cost and retention policy, and monitor non-zero exits.

Custom transports

File::upload(array|Closure $descriptor) replaces the nested headless upload descriptor. temporaryUploadUrl() and temporaryUploadDeleteUrl() override the normal temporary endpoints. When using application endpoints:

  • return the token/file payload expected by the Vue upload transport or provide a custom Vue transport;
  • validate the actual uploaded content rather than trusting client MIME type or filename;
  • issue expiring, tamper-resistant submission references;
  • authorize deletion as well as creation;
  • keep cleanup and abandoned-session handling explicit.

Custom endpoints are outside the package route and token guarantees unless the application deliberately implements equivalent controls.

Copyright © 2026 Inertify · Released under the MIT License