Kotchasan Framework Documentation

Kotchasan Framework Documentation

Files Class - Uploaded Files Collection

EN 05 Feb 2026 07:40

Files Class - Uploaded Files Collection

The Files class is an Iterator for managing collections of uploaded files, used with UploadedFile within the Kotchasan Framework.

Namespace

Kotchasan\Files

Overview

The Files class implements the \Iterator interface, allowing it to be used in foreach loops.

API Reference

__construct()

Create a new instance of the file collection

public function __construct()

Example:

use Kotchasan\Files;

// Create new file collection
$files = new Files();

add()

Add a file to the collection

public function add($name, $path, $originalName, $mimeType = null, $size = null, $error = null)

Parameters:

  • $name - Input name
  • $path - Uploaded file path
  • $originalName - Original filename
  • $mimeType - MIME Type (optional)
  • $size - File size (optional)
  • $error - Error code UPLOAD_ERR_XXX (optional)

Returns: void

Example:

use Kotchasan\Files;

$files = new Files();

// Add image file
$files->add('profile_image', '/tmp/upload123', 'avatar.jpg', 'image/jpeg', 1024000, UPLOAD_ERR_OK);

// Add document file
$files->add('document', '/tmp/upload124', 'resume.pdf', 'application/pdf', 2048000, UPLOAD_ERR_OK);

// Add file with error
$files->add('large_file', '/tmp/upload125', 'video.mp4', 'video/mp4', 50000000, UPLOAD_ERR_FORM_SIZE);

// Use with $_FILES data
foreach ($_FILES as $inputName => $fileData) {
    if (is_array($fileData['name'])) {
        // Multiple files
        for ($i = 0; $i < count($fileData['name']); $i++) {
            $files->add(
                $inputName,
                $fileData['tmp_name'][$i],
                $fileData['name'][$i],
                $fileData['type'][$i],
                $fileData['size'][$i],
                $fileData['error'][$i]
            );
        }
    } else {
        // Single file
        $files->add(
            $inputName,
            $fileData['tmp_name'],
            $fileData['name'],
            $fileData['type'],
            $fileData['size'],
            $fileData['error']
        );
    }
}

get()

Get file by specified key

public function get($key)

Parameters:

  • $key (string|int) - The requested key

Returns: \Kotchasan\Http\UploadedFile|null - UploadedFile object or null if not found

Example:

use Kotchasan\Files;

$files = new Files();
$files->add('profile', '/tmp/upload123', 'avatar.jpg', 'image/jpeg', 1024000, UPLOAD_ERR_OK);
$files->add('document', '/tmp/upload124', 'resume.pdf', 'application/pdf', 2048000, UPLOAD_ERR_OK);

// Get profile file
$profileFile = $files->get('profile');
if ($profileFile) {
    echo "Profile: " . $profileFile->getClientFilename();
    echo "Size: " . $profileFile->getSize() . " bytes";
}

// Get document file
$documentFile = $files->get('document');
if ($documentFile) {
    echo "Document: " . $documentFile->getClientFilename();
    echo "Type: " . $documentFile->getClientMediaType();
}

// Check for non-existent file
$missingFile = $files->get('nonexistent');
if ($missingFile === null) {
    echo "File not found";
}

Iterator Methods

The Files class implements the Iterator interface to be usable in foreach loops

public function rewind()          // Reset to first
public function valid()            // Check if data exists (returns bool)
public function current()          // Get current file (returns UploadedFile)
public function key()              // Get current key (returns string)
public function next()             // Move to next file

Example:

use Kotchasan\Files;
use Kotchasan\File;

$files = new Files();
$files->add('image1', '/tmp/upload1', 'photo1.jpg', 'image/jpeg', 1024000, UPLOAD_ERR_OK);
$files->add('image2', '/tmp/upload2', 'photo2.png', 'image/png', 2048000, UPLOAD_ERR_OK);
$files->add('document', '/tmp/upload3', 'doc.pdf', 'application/pdf', 3072000, UPLOAD_ERR_OK);

// Loop through all files
foreach ($files as $inputName => $uploadedFile) {
    echo "Input: {$inputName}\n";
    echo "Filename: " . $uploadedFile->getClientFilename() . "\n";
    echo "Size: " . $uploadedFile->getSize() . " bytes\n";
    echo "Type: " . $uploadedFile->getClientMediaType() . "\n";
    echo "Status: " . ($uploadedFile->getError() === UPLOAD_ERR_OK ? 'Success' : 'Error') . "\n";
    echo "---\n";
}

// Process all files example
function processAllFiles($files) {
    $results = [];

    foreach ($files as $inputName => $uploadedFile) {
        $result = [
            'input_name' => $inputName,
            'original_name' => $uploadedFile->getClientFilename(),
            'size' => $uploadedFile->getSize(),
            'type' => $uploadedFile->getClientMediaType(),
            'error' => $uploadedFile->getError(),
            'processed' => false,
            'message' => ''
        ];

        if ($uploadedFile->getError() === UPLOAD_ERR_OK) {
            // Process file
            $extension = File::ext($uploadedFile->getClientFilename());
            $allowedTypes = ['jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx'];

            if (in_array($extension, $allowedTypes)) {
                $result['processed'] = true;
                $result['message'] = 'File processed successfully';
            } else {
                $result['message'] = 'File type not allowed';
            }
        } else {
            $result['message'] = 'Upload error: ' . $uploadedFile->getError();
        }

        $results[] = $result;
    }

    return $results;
}

// Filter files by type example
function filterFilesByType($files, $allowedTypes) {
    $filtered = new Files();

    foreach ($files as $inputName => $uploadedFile) {
        $extension = File::ext($uploadedFile->getClientFilename());

        if (in_array($extension, $allowedTypes)) {
            $filtered->add(
                $inputName,
                $uploadedFile->getStream()->getMetadata('uri'),
                $uploadedFile->getClientFilename(),
                $uploadedFile->getClientMediaType(),
                $uploadedFile->getSize(),
                $uploadedFile->getError()
            );
        }
    }

    return $filtered;
}

// Generate upload report example
function generateUploadReport($files) {
    $report = [
        'total_files' => 0,
        'successful_uploads' => 0,
        'failed_uploads' => 0,
        'total_size' => 0,
        'file_types' => [],
        'errors' => []
    ];

    foreach ($files as $inputName => $uploadedFile) {
        $report['total_files']++;

        if ($uploadedFile->getError() === UPLOAD_ERR_OK) {
            $report['successful_uploads']++;
            $report['total_size'] += $uploadedFile->getSize();

            $extension = File::ext($uploadedFile->getClientFilename());
            $report['file_types'][$extension] = ($report['file_types'][$extension] ?? 0) + 1;
        } else {
            $report['failed_uploads']++;
            $report['errors'][] = [
                'input_name' => $inputName,
                'filename' => $uploadedFile->getClientFilename(),
                'error_code' => $uploadedFile->getError()
            ];
        }
    }

    return $report;
}

Real-World Examples

1. Image Upload Manager System

use Kotchasan\Files;
use Kotchasan\File;
use Kotchasan\Image;

class ImageUploadManager
{
    public static function processImageUploads($files, $uploadDir)
    {
        $results = [];

        foreach ($files as $inputName => $uploadedFile) {
            if ($uploadedFile->getError() !== UPLOAD_ERR_OK) {
                $results[] = [
                    'input_name' => $inputName,
                    'success' => false,
                    'message' => 'Upload error: ' . $uploadedFile->getError()
                ];
                continue;
            }

            $extension = File::ext($uploadedFile->getClientFilename());
            if (!in_array($extension, ['jpg', 'jpeg', 'png', 'gif'])) {
                $results[] = [
                    'input_name' => $inputName,
                    'success' => false,
                    'message' => 'File type is not an image'
                ];
                continue;
            }

            // Generate new filename
            $newFilename = uniqid() . '.' . $extension;
            $targetPath = $uploadDir . $newFilename;

            // Move file
            $uploadedFile->moveTo($targetPath);

            // Create thumbnail
            $thumbnailPath = $uploadDir . 'thumbs/' . $newFilename;
            File::makeDirectory(dirname($thumbnailPath));
            Image::crop($targetPath, $thumbnailPath, 200, 200);

            $results[] = [
                'input_name' => $inputName,
                'success' => true,
                'original_name' => $uploadedFile->getClientFilename(),
                'saved_name' => $newFilename,
                'path' => $targetPath,
                'thumbnail' => $thumbnailPath,
                'size' => $uploadedFile->getSize()
            ];
        }

        return $results;
    }
}

2. Document Upload Manager System

class DocumentUploadManager
{
    public static function processDocumentUploads($files, $uploadDir, $userId)
    {
        $userDir = $uploadDir . "user_{$userId}/";
        File::makeDirectory($userDir);

        $results = [];

        foreach ($files as $inputName => $uploadedFile) {
            if ($uploadedFile->getError() !== UPLOAD_ERR_OK) {
                $results[] = [
                    'input_name' => $inputName,
                    'success' => false,
                    'message' => 'Upload error'
                ];
                continue;
            }

            $extension = File::ext($uploadedFile->getClientFilename());
            $allowedTypes = ['pdf', 'doc', 'docx', 'txt', 'xls', 'xlsx'];

            if (!in_array($extension, $allowedTypes)) {
                $results[] = [
                    'input_name' => $inputName,
                    'success' => false,
                    'message' => 'Document type not allowed'
                ];
                continue;
            }

            // Check file size (10MB max)
            if ($uploadedFile->getSize() > 10 * 1024 * 1024) {
                $results[] = [
                    'input_name' => $inputName,
                    'success' => false,
                    'message' => 'File size exceeds limit (max 10MB)'
                ];
                continue;
            }

            $safeFilename = date('Y-m-d_H-i-s') . '_' . $uploadedFile->getClientFilename();
            $targetPath = $userDir . $safeFilename;

            $uploadedFile->moveTo($targetPath);

            $results[] = [
                'input_name' => $inputName,
                'success' => true,
                'original_name' => $uploadedFile->getClientFilename(),
                'saved_name' => $safeFilename,
                'path' => $targetPath,
                'size' => $uploadedFile->getSize(),
                'type' => $uploadedFile->getClientMediaType()
            ];
        }

        return $results;
    }
}

3. Multi-File Upload System

class MultiFileUploader
{
    public function handleUpload()
    {
        $files = new Files();

        // Process $_FILES data
        foreach ($_FILES as $inputName => $fileData) {
            if (is_array($fileData['name'])) {
                // Multiple files
                for ($i = 0; $i < count($fileData['name']); $i++) {
                    if (!empty($fileData['name'][$i])) {
                        $files->add(
                            $inputName . '[' . $i . ']',
                            $fileData['tmp_name'][$i],
                            $fileData['name'][$i],
                            $fileData['type'][$i],
                            $fileData['size'][$i],
                            $fileData['error'][$i]
                        );
                    }
                }
            } else {
                // Single file
                if (!empty($fileData['name'])) {
                    $files->add(
                        $inputName,
                        $fileData['tmp_name'],
                        $fileData['name'],
                        $fileData['type'],
                        $fileData['size'],
                        $fileData['error']
                    );
                }
            }
        }

        return $this->processFiles($files);
    }

    private function processFiles($files)
    {
        $uploadDir = ROOT_PATH . 'datas/uploads/' . date('Y/m/d') . '/';
        File::makeDirectory($uploadDir);

        $results = [
            'uploaded' => [],
            'failed' => [],
            'summary' => [
                'total' => 0,
                'success' => 0,
                'failed' => 0
            ]
        ];

        foreach ($files as $inputName => $uploadedFile) {
            $results['summary']['total']++;

            $result = $this->processFile($uploadedFile, $uploadDir);
            $result['input_name'] = $inputName;

            if ($result['success']) {
                $results['uploaded'][] = $result;
                $results['summary']['success']++;
            } else {
                $results['failed'][] = $result;
                $results['summary']['failed']++;
            }
        }

        return $results;
    }

    private function processFile($uploadedFile, $uploadDir)
    {
        if ($uploadedFile->getError() !== UPLOAD_ERR_OK) {
            return [
                'success' => false,
                'message' => $this->getUploadErrorMessage($uploadedFile->getError()),
                'original_name' => $uploadedFile->getClientFilename()
            ];
        }

        $extension = File::ext($uploadedFile->getClientFilename());
        $allowedTypes = ['jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx'];

        if (!in_array($extension, $allowedTypes)) {
            return [
                'success' => false,
                'message' => 'File type not allowed',
                'original_name' => $uploadedFile->getClientFilename()
            ];
        }

        $filename = uniqid() . '_' . $uploadedFile->getClientFilename();
        $targetPath = $uploadDir . $filename;

        try {
            $uploadedFile->moveTo($targetPath);

            return [
                'success' => true,
                'message' => 'Upload successful',
                'original_name' => $uploadedFile->getClientFilename(),
                'saved_name' => $filename,
                'path' => $targetPath,
                'size' => $uploadedFile->getSize(),
                'url' => str_replace(ROOT_PATH, WEB_URL, $targetPath)
            ];
        } catch (Exception $e) {
            return [
                'success' => false,
                'message' => 'Cannot save file: ' . $e->getMessage(),
                'original_name' => $uploadedFile->getClientFilename()
            ];
        }
    }

    private function getUploadErrorMessage($errorCode)
    {
        $messages = [
            UPLOAD_ERR_INI_SIZE => 'File size exceeds system limit',
            UPLOAD_ERR_FORM_SIZE => 'File size exceeds form limit',
            UPLOAD_ERR_PARTIAL => 'File was partially uploaded',
            UPLOAD_ERR_NO_FILE => 'No file was uploaded',
            UPLOAD_ERR_NO_TMP_DIR => 'Temporary directory not found',
            UPLOAD_ERR_CANT_WRITE => 'Cannot write file to disk',
            UPLOAD_ERR_EXTENSION => 'Upload stopped by extension'
        ];

        return $messages[$errorCode] ?? 'Unknown error';
    }
}

// Use in controller
class UploadController extends \Kotchasan\Controller
{
    public function upload()
    {
        if ($this->request->getMethod() === 'POST') {
            $uploader = new MultiFileUploader();
            $results = $uploader->handleUpload();

            // Return results as JSON
            header('Content-Type: application/json');
            echo json_encode($results);
        } else {
            // Show upload form
            include ROOT_PATH . 'modules/upload/views/form.php';
        }
    }
}

Usage Notes

  1. Iterator Pattern: Can be used directly in foreach loops
  2. UploadedFile: Works with PSR-7 UploadedFile interface
  3. Memory Efficient: Stores only references, doesn't load entire files into memory
  4. Flexible: Supports both single and multiple file uploads
  • [File] - File and directory management
  • Image - Image processing
  • UploadedFile - PSR-7 UploadedFile

Summary

Files class has 6 main methods:

  1. __construct() - Create file collection
  2. add() - Add file to collection
  3. get() - Get file by key
  4. rewind() - Reset iterator
  5. valid() - Check if data exists
  6. current(), key(), next() - Iterator methods

Perfect for:

  • Image upload systems
  • Document upload systems
  • Multi-file upload systems
  • User file management systems