Loki_UploadFieldComponents

Core
module.field-components
PHP 8.1 - 8.4
Magento 2.4.7 | 2.4.8
CSP Yes
PHPStan 1
Magento PHPCS 8

File upload field component for Loki Checkout and Loki Field Components.

Overview

This module provides a reusable file upload field component that integrates with the Loki Field Components architecture. It allows developers to easily add file upload functionality to forms, checkouts, or any other frontend context where Loki Components are used.

Features

  • Configurable Upload Location: Files are stored in pub/media/order_attachment/ by default (configurable)
  • Configurable File Types: Images (jpg, jpeg, png, gif, webp) by default (configurable)
  • Configurable File Size: Uses Magento default limits (configurable)
  • Single File Upload: Optimized for single file uploads
  • Alpine.js Integration: Automatic upload on file selection
  • Extensible Architecture: Easy to extend with custom repositories and configurations

Installation

composer require loki/magento2-upload-field-components
bin/magento module:enable Loki_UploadFieldComponents
bin/magento setup:upgrade
bin/magento cache:clean config

Basic Usage

Add an upload field to any layout XML:

<block name="my.upload.field" template="Loki_FieldComponents::form/field.phtml">
    <arguments>
        <argument name="field_type" xsi:type="string">upload</argument>
        <argument name="field_name" xsi:type="string">my_file</argument>
        <argument name="field_label" xsi:type="string" translate="true">Upload File</argument>
        <argument name="required" xsi:type="boolean">false</argument>
        <argument name="component_name" xsi:type="string">loki-field-components.upload</argument>
    </arguments>
</block>

Advanced Configuration

Custom Upload Path

To change the upload directory, create a virtual type in your module's di.xml:

<!-- Custom upload path: pub/media/custom_uploads/ -->
<virtualType name="YourModule\Model\CustomUploadConfig" 
             type="Loki\UploadFieldComponents\Model\Config\UploadConfig">
    <arguments>
        <argument name="uploadPath" xsi:type="string">custom_uploads</argument>
    </arguments>
</virtualType>

<virtualType name="YourModule\Model\CustomFileUploader" 
             type="Loki\UploadFieldComponents\Model\FileUploader">
    <arguments>
        <argument name="config" xsi:type="object">YourModule\Model\CustomUploadConfig</argument>
    </arguments>
</virtualType>

<type name="YourModule\Component\CustomUpload\CustomUploadRepository">
    <arguments>
        <argument name="fileUploader" xsi:type="object">YourModule\Model\CustomFileUploader</argument>
    </arguments>
</type>

Custom File Types (PDF Only)

<virtualType name="YourModule\Model\PdfUploadConfig" 
             type="Loki\UploadFieldComponents\Model\Config\UploadConfig">
    <arguments>
        <argument name="uploadPath" xsi:type="string">pdf_documents</argument>
        <argument name="allowedExtensions" xsi:type="array">
            <item name="pdf" xsi:type="string">pdf</item>
        </argument>
        <argument name="maxFileSizeMb" xsi:type="number">10</argument>
    </arguments>
</virtualType>

Custom File Size Limit

<type name="Loki\UploadFieldComponents\Model\Config\UploadConfig">
    <arguments>
        <argument name="maxFileSizeMb" xsi:type="number">5</argument>
    </arguments>
</type>

Extending the Repository

To add custom logic after file upload (e.g., save file reference to quote or database):

<?php
declare(strict_types=1);

namespace YourModule\Component\CustomUpload;

use Loki\UploadFieldComponents\Component\UploadField\UploadFieldRepository;
use Magento\Quote\Model\Quote;

class CustomUploadRepository extends UploadFieldRepository
{
    public function __construct(
        private Quote $quote,
        ...$parentArgs
    ) {
        parent::__construct(...$parentArgs);
    }

    protected function afterFileUpload(array $uploadResult): void
    {
        // Save the file path to the quote
        $this->quote->setData('attachment_path', $uploadResult['path']);
        $this->quote->setData('attachment_name', $uploadResult['name']);
        $this->quote->save();
    }

    public function getValue(): mixed
    {
        // Return the saved file path
        return $this->quote->getData('attachment_path') ?: false;
    }
}

Register your custom repository in etc/loki_components.xml:

<component
    name="your-module.custom-upload"
    viewModel="Loki\UploadFieldComponents\Component\UploadField\UploadFieldViewModel"
    repository="YourModule\Component\CustomUpload\CustomUploadRepository"
/>

Use it in layout XML:

<block name="my.custom.upload" template="Loki_FieldComponents::form/field.phtml">
    <arguments>
        <argument name="field_type" xsi:type="string">upload</argument>
        <argument name="field_name" xsi:type="string">custom_upload</argument>
        <argument name="component_name" xsi:type="string">your-module.custom-upload</argument>
    </arguments>
</block>

Architecture

Component Structure

  • UploadConfig: Configuration class for upload settings (path, extensions, size limit)
  • FileUploader: Utility class that handles the actual file upload using Magento's UploaderFactory
  • UploadFieldRepository: Repository that coordinates file upload and provides extension hooks
  • UploadFieldViewModel: View model for rendering the upload field

Upload Flow

  1. User selects a file in the browser
  2. Alpine.js @change event triggers submitValue
  3. File is sent to loki_components/index/html controller
  4. Repository's saveValue() method is called
  5. FileUploader validates and uploads the file
  6. afterFileUpload() hook is called for custom logic
  7. Success/error message is displayed to the user

File Storage

By default, files are stored in:

pub/media/order_attachment/

The uploaded file name may be renamed if a file with the same name already exists (e.g., file.jpg becomes file_1.jpg).

Dependencies

  • Loki_Components - Base component architecture
  • Loki_FieldComponents - Field component base classes
  • Magento_MediaStorage - File upload handling

Configuration Options

UploadConfig Constructor Parameters

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | uploadPath | string | order_attachment | Directory path relative to pub/media/ | | allowedExtensions | array | ['jpg', 'jpeg', 'png', 'gif', 'webp'] | Allowed file extensions | | maxFileSizeMb | int|null | null | Max file size in MB (null = Magento default) |

Extension Points

afterFileUpload(array $uploadResult): void

Called after successful file upload. Override this method in your custom repository to add post-upload logic.

Upload Result Array:

[
    'file' => 'filename.jpg',           // Uploaded file name
    'path' => 'order_attachment/filename.jpg',  // Relative path
    'absolute_path' => '/path/to/pub/media/order_attachment/filename.jpg',
    'name' => 'original_name.jpg',      // Original file name
    'type' => 'image/jpeg',             // MIME type
    'size' => 12345                     // File size in bytes
]

Limitations

  • Single file upload only (multiple file upload not supported)
  • No built-in file preview functionality
  • No built-in database storage (must be implemented by extending modules)
  • Files are not automatically deleted when orders are cancelled

Future Enhancements

  • Multiple file upload support
  • File preview after selection
  • Database table for file metadata
  • Integration with quote/order lifecycle
  • File cleanup cron job for orphaned files
  • Admin configuration interface

Troubleshooting

Files not uploading

  1. Check PHP settings:

    • upload_max_filesize (default: 2M)
    • post_max_size (default: 8M)
    • max_execution_time (default: 30s)
  2. Check directory permissions:

    chmod 775 pub/media/order_attachment/
    
  3. Check error messages in browser console and Magento logs:

    tail -f var/log/system.log
    

File type not accepted

Make sure the file extension is in the allowedExtensions array in your UploadConfig.

File size limit exceeded

Either reduce the file size or increase the maxFileSizeMb setting in your UploadConfig. Note that PHP's upload_max_filesize setting must also be increased.

License

OSL-3.0

Author

Loki Extensions

Support

For issues and questions, please visit:

  • GitHub: https://github.com/loki-extensions
  • Documentation: https://loki-extensions.com
WARNING: This module has no releases yet. If you want to use it, make sure to add the version @dev to the composer command.

Support

For getting support, create an Issue under the following project URL:

https://gitlab.yireo.com/loki-checkout/Loki_UploadFieldComponents.git

Composer details
Magento module name
Loki_UploadFieldComponents
Composer name
loki/magento2-upload-field-components
Composer version
No release yet
Default branch
main
Requirements
php: ^8.1|^8.2|^8.3
magento/framework: *
loki/magento2-components: *
loki/magento2-field-components: *
Releases
Changelog

Last modified: June 1, 2026