Files

Upload

Upload service flow, file validation boundaries, storage strategies a příklady zpracování souborů.

Overview

Upload module handles file and image uploads from PSR-7 requests. It resolves uploaded payloads, validates input, stores files into upload storage, and returns typed results (UploadedFile / UploadedImage).

Registered services

UploadServiceProvider registers only typed service IDs (no string aliases): FileUploadValidator, ImageUploadValidator, UploadStorage, MimeTypeDetector, GdImageProcessor, UploadService, and UploadFactory.

Configuration

Upload profiles are configured in app/Config/Upload.php under upload.files.profiles and upload.images.profiles.

return [
    'upload' => [
        'files' => [
            'profiles' => [
                'documents' => [
                    'target_directory' => 'uploads/documents',
                    'max_bytes' => 10 * 1024 * 1024,
                    'allowed_mime_types' => [
                        'application/pdf',
                        'text/plain',
                    ],
                    'allowed_extensions' => [
                        'pdf',
                        'txt',
                    ],
                ],
            ],
        ],
        'images' => [
            'profiles' => [
                'avatar' => [
                    'target_directory' => 'uploads/avatars',
                    'max_bytes' => 2 * 1024 * 1024,
                    'allowed_mime_types' => [
                        'image/jpeg',
                        'image/png',
                        'image/webp',
                    ],
                    'allowed_extensions' => [
                        'jpg',
                        'jpeg',
                        'png',
                        'webp',
                    ],
                    'reencode' => true,
                    'min_width' => 128,
                    'min_height' => 128,
                    'max_width' => 2048,
                    'max_height' => 2048,
                ],
            ],
        ],
    ],
];

Uploaded files in controllers

Controller exposes uploaded file access helper file() and upload helper upload() (UploadFactory).

$raw = $this->file('avatar'); // UploadedFileInterface|array|null

$image = $this->upload()->uploadImage('avatar', 'avatar');
$document = $this->upload()->upload('document', 'documents');

Upload service

Use dependency injection for application services. UploadFactory is the high-level entrypoint and supports profile-based or explicit-options workflows.

final class ProfileImageUploader
{
    public function __construct(
        private readonly UploadFactory $uploads,
    ) {
    }

    public function uploadAvatar(ServerRequestInterface $request): UploadedImage
    {
        return $this->uploads
            ->image('avatar')
            ->uploadFromRequest($request, 'avatar');
    }
}

Validation

FileUploadValidator validates upload payload presence, PHP upload error, temporary file path, size, MIME type and extension. ImageUploadValidator adds image readability and optional width/height constraints. Validation failures throw UploadValidationException.

Storage paths

Upload options are resolved through ApplicationContext. target_directory from config is transformed to absolute storage path via resolveUploadPath() and to portable relative path via uploadRelativePath().

$absolute = $context->resolveUploadPath('uploads/avatars');
// .../storage/uploads/avatars

$relative = $context->uploadRelativePath('uploads/avatars');
// uploads/avatars

Security notes

Do not trust client filenames. Validate size/type/extension through profile rules. Prefer generated storage filenames (UploadStorage::generateFilename()) and persist only stored metadata (storedRelativePath, mime, size). Keep executable files out of publicly executable directories.

Example

Typical safe workflow: read file from request, validate via profile, store upload, persist only resulting metadata.

public function uploadAvatarAction(): ResponseInterface
{
    $uploaded = $this->upload()->uploadImage('avatar', 'avatar');

    // Persist only stable metadata, not original client filename.
    $payload = [
        'path' => $uploaded->storedRelativePath(),
        'mime' => $uploaded->mimeType(),
        'size' => $uploaded->sizeBytes(),
        'width' => $uploaded->width(),
        'height' => $uploaded->height(),
    ];

    return $this->json($payload, 201);
}