PHPackages                             karelwintersky/arris.php-file-upload - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [File &amp; Storage](/categories/file-storage)
4. /
5. karelwintersky/arris.php-file-upload

ActiveLibrary[File &amp; Storage](/categories/file-storage)

karelwintersky/arris.php-file-upload
====================================

Powerful PHP8 file upload library with validation, conversion, and fluent interface

0.3.0(1mo ago)018[1 issues](https://github.com/ArrisFramework/Arris.Toolkit.FileUpload/issues)MITPHPPHP ^8.2

Since Jul 12Pushed 2y ago1 watchersCompare

[ Source](https://github.com/ArrisFramework/Arris.Toolkit.FileUpload)[ Packagist](https://packagist.org/packages/karelwintersky/arris.php-file-upload)[ RSS](/packages/karelwintersky-arrisphp-file-upload/feed)WikiDiscussions master Synced 2w ago

READMEChangelog (4)Dependencies (2)Versions (7)Used By (0)

FileUpload - PHP8 File Upload Library
=====================================

[](#fileupload---php8-file-upload-library)

Библиотека для загрузки файлов с валидацией, конвертацией изображений и Fluent Interface.

Требования
----------

[](#требования)

- PHP 8.2+
- ext-fileinfo
- ext-gd (опционально, для конверсии изображений)

Установка
---------

[](#установка)

```
composer require karelwintersky/arris.php-file-upload
```

Быстрый старт
-------------

[](#быстрый-старт)

```
use Arris\Toolkit\FileUpload;

$upload = FileUpload::fromFile($_FILES['photo'], 0)
    ->setTargetPath('/var/www/uploads/')
    ->allowMimeTypes(['image/jpeg', 'image/png'])
    ->setMaxFileSize(5 * 1024 * 1024);

$result = $upload->process();

if ($result->isSuccess) {
    echo $result->fullPath;
} else {
    echo implode(', ', $result->errors);
}
```

Два этапа загрузки
------------------

[](#два-этапа-загрузки)

### 1. `uploaded()` — проверка первичной загрузки

[](#1-uploaded--проверка-первичной-загрузки)

Проверяет `is_uploaded_file()`, выполняет полную валидацию (MIME, размер, кастомные валидаторы). Возвращает `FileUploadResult` с stage=`uploaded`. На этапе `uploaded` уже доступны `size` и `mimeType`.

```
$upload = FileUpload::fromFile($_FILES['photo'], 0);

$check = $upload->uploaded();

if (!$check->isSuccess) {
    echo $check->errors[0];
    echo $check->size; // размер файла доступен даже при ошибке
}
```

### 2. `process()` — конверсия, сохранение

[](#2-process--конверсия-сохранение)

Если `uploaded()` уже вызван и прошёл успешно — `process()` **пропускает** валидацию (флаг `validated`). Если вызван напрямую — выполняет валидацию сам.

```
$result = $upload->process();

if ($result->isSuccess) {
    echo $result->savedName;    // "2024_01_15__a1b2c3d4.jpg"
    echo $result->fullPath;     // "/var/www/uploads/2024_01_15__a1b2c3d4.jpg"
    echo $result->radix;        // "2024_01_15__a1b2c3d4"
    echo $result->mimeType;     // "image/jpeg"
    echo $result->size;         // 102400
    echo $result->width;        // 1920 (для изображений)
    echo $result->height;       // 1080 (для изображений)
}
```

Конфигурация
------------

[](#конфигурация)

### Дефолтный конфиг (один раз при бутстрапе)

[](#дефолтный-конфиг-один-раз-при-бутстрапе)

```
FileUpload::setDefaultConfig([
    'targetPath'        => '/var/www/uploads/',
    'allowedMimeTypes'  => ['image/jpeg', 'image/png', 'image/webp'],
    'maxFileSize'       => 10 * 1024 * 1024,
    'minFileSize'       => 1024,
    'filenameGenerator' => function (string $originalName, array $file) {
        $ext = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
        return date('Y_m_d_') . uniqid(more_entropy: true) . ".{$ext}";
    },
    'throwExceptions'   => false,
]);
```

### Опция через `applyOption()`

[](#опция-через-applyoption)

```
FileUpload::applyOption('targetPath', '/var/www/photos/');
FileUpload::applyOption('targetMimeType', 'image/webp');
FileUpload::applyOption('targetImageQuality', 85);
FileUpload::applyOption('minFileSize', 1024);
FileUpload::applyOption('locale', 'en');
```

### Fluent-конфигурация на инстансе

[](#fluent-конфигурация-на-инстансе)

```
$upload = FileUpload::fromFile($_FILES['photo'], 0)
    ->setTargetPath('/var/www/uploads/')
    ->allowMimeTypes(['image/jpeg', 'image/png'])
    ->setMaxFileSize(5 * 1024 * 1024)
    ->setMinFileSize(1024)
    ->setTargetMimeType('image/webp', 85)
    ->setLocale('en')
    ->setFilenameGenerator(fn($name) => uniqid() . '.' . pathinfo($name, PATHINFO_EXTENSION));
```

Валидация
---------

[](#валидация)

### Встроенные валидаторы

[](#встроенные-валидаторы)

```
$upload = FileUpload::fromFile($_FILES['photo'], 0)
    ->allowMimeTypes(['image/jpeg', 'image/png'])
    ->setMaxFileSize(5 * 1024 * 1024)
    ->setMinFileSize(1024);
```

### Кастомные валидаторы

[](#кастомные-валидаторы)

Функции-коллбэки, которые принимают массив файла и возвращают:

- `true` — валидация пройдена
- `false` — валидация не пройдена, в ошибки запишется дефолтное сообщение "Ошибка валидации файла"
- строка — валидация не пройдена, в ошибки запишется указанная строка

```
$upload = FileUpload::fromFile($_FILES['document'], 0)
    ->setTargetPath('/var/www/docs/')
    ->addValidator(function (array $file): bool|string {
        if ($file['size'] < 1024) {
            return 'Файл слишком маленький (минимум 1KB)';
        }
        return true;
    })
    ->addValidator(function (array $file): bool|string {
        if (preg_match('/[^a-zA-Z0-9._-]/', $file['name'])) {
            return 'Имя файла содержит недопустимые символы';
        }
        return true;
    });
```

### Порядок и collect-all

[](#порядок-и-collect-all)

Валидация выполняется в следующем порядке:

1. **Прекондишины** (fail-fast): файл не задан → не загружен через HTTP → PHP upload-ошибка
2. **Встроенные валидаторы**: MIME-тип → минимальный размер → максимальный размер
3. **Кастомные валидаторы**: все по порядку

Встроенные и кастомные валидаторы работают в режиме **collect-all**: все проверки выполняются, все ошибки собираются. Пользователь видит **все** проблемы сразу, а не только первую попавшуюся.

```
// Пример: файл слишком маленький + неверный MIME — обе ошибки в одном ответе
FileUpload::applyOption('allowedMimeTypes', ['image/png']);
FileUpload::applyOption('minFileSize', 300 * 1024);

$result = $upload->uploaded();
// $result->errors = ['Файл слишком маленький', 'Недопустимый тип файла: image/jpeg']
```

Конверсия изображений
---------------------

[](#конверсия-изображений)

Конвертирует изображение из одного формата в другой при перемещении в storage.

Для этого нужно указать целевой mime-тип и качество. Третий параметр `$force` заставляет применить конвертер даже если целевой mime-тип совпадает с исходным — это позволяет приводить загруженные фотографии к общему стандарту (пережатие).

```
$upload = FileUpload::fromFile($_FILES['photo'], 0)
    ->setTargetPath('/var/www/images/')
    ->allowMimeTypes(['image/jpeg', 'image/png'])
    ->setTargetMimeType('image/webp', 85);

$result = $upload->process();

if ($result->isSuccess) {
    echo $result->extension; // "webp"
}
```

### Принудительная конвертация (`$force`)

[](#принудительная-конвертация-force)

```
// JPEG → JPEG, но с пережатием до качества 75
$upload->setTargetMimeType('image/jpeg', 75, true);
```

### Кастомный конвертер

[](#кастомный-конвертер)

```
FileUpload::applyOption('conversionCallback', function (
    string $sourcePath,
    string $targetPath,
    string $targetMime,
    int $quality
): bool {
    return copy($sourcePath, $targetPath);
});
```

### Поддерживаемые форматы

[](#поддерживаемые-форматы)

ФорматИсточникЦельJPEGyesyesPNGyesyesGIFyesyesWebPyesyesBMPyes—Система ошибок
--------------

[](#система-ошибок)

### Коды ошибок

[](#коды-ошибок)

Каждая ошибка имеет код `FileUploadErrorCode` (backed enum). Доступны через `getErrorStack()`:

```
$stack = $upload->getErrorStack();
// [
//     ['code' => ErrorCode::FILE_TOO_LARGE, 'params' => []],
//     ['code' => ErrorCode::VALIDATOR_FAILED, 'params' => ['message' => 'Файл повреждён']],
// ]

foreach ($stack as $entry) {
    echo $entry['code']->value; // 'file_too_large'
}
```

### Трансляция сообщений

[](#трансляция-сообщений)

`getErrors()` возвращает массив человекочитаемых строк (через `FileUploadErrorMessages`):

```
$errors = $upload->getErrors();
// ['Файл слишком большой', 'Файл повреждён']
```

### Кастомизация сообщений

[](#кастомизация-сообщений)

```
use Arris\Toolkit\FileUpload\ErrorCode;
use Arris\Toolkit\FileUpload\ErrorMessages;

// Одно сообщение
ErrorMessages::setMessage(
    ErrorCode::FILE_TOO_LARGE,
    'Максимум 10 МБ!'
);

// Пакетная замена (удобно для i18n)
ErrorMessages::setMessages([
    'file_too_large'  => 'Maximum 10 MB',
    'file_too_small'  => 'Minimum 1 KB',
    'invalid_mime_type' => 'Unsupported file type: {mime_type}',
    'validator_failed'  => '{message}',
]);
```

Параметры в шаблонах: `{mime_type}`, `{message}` — подставляются из params.

### Локализация (i18n)

[](#локализация-i18n)

Встроенные locales: `ru` (по умолчанию) и `en`.

```
use Arris\Toolkit\FileUpload;

// На инстансе
$upload = FileUpload::fromFile($_FILES['file'])
    ->setLocale('en');

// Глобально через конфиг
FileUpload::setDefaultConfig([
    'locale' => 'en',
]);

// Или через applyOption
FileUpload::applyOption('locale', 'en');

// Принудительно для текущего результата
$errors = $upload->setLocale('ru')->getErrors();
```

### Обработка ошибок

[](#обработка-ошибок)

#### Тихий режим (по умолчанию)

[](#тихий-режим-по-умолчанию)

```
$result = $upload->process();

if (!$result->isSuccess) {
    echo $result->lastError;
    print_r($result->errors);
}
```

#### Режим исключений

[](#режим-исключений)

```
use Arris\Toolkit\FileUploadException;

FileUpload::applyOption('throwExceptions', true);

try {
    $result = $upload->process();
} catch (FileUploadException $e) {
    echo $e->getMessage();
    print_r($e->getErrors());
}
```

Множественная загрузка
----------------------

[](#множественная-загрузка)

```
$photoKeys = array_keys($_FILES['photos']['tmp_name']);

foreach ($photoKeys as $photoId) {
    $upload = FileUpload::fromFile($_FILES['photos'], $photoId);

    $check = $upload->uploaded();
    if (!$check->isSuccess) {
        continue;
    }

    $result = $upload->process();
    if ($result->isSuccess) {
        // сохраняем $result->radix, $result->mimeType, etc.
    }
}
```

FileUploadResult
----------------

[](#fileuploadresult)

Объект возвращаемый `uploaded()` и `process()`.

ПолеТипОписание`isSuccess``bool`Успешность операции`stage``string|null``'uploaded'` или `'processed'``originalName``string|null`Оригинальное имя файла`savedName``string|null`Имя файла в storage`path``string|null`Путь к каталогу storage`fullPath``string|null`Полный путь к файлу`mimeType``string|null`MIME-тип`size``int|null`Размер в байтах`lastError``string|null`Последняя ошибка`errors``array`Массив ошибок`radix``string|null`Имя файла без расширения`extension``string|null`Расширение без точки`width``int|null`Ширина (image/\*)`height``int|null`Высота (image/\*)```
// Сериализация
$result->toJson();      // JSON строка
$result->toJson(true);  // JSON с форматированием
$result->toArray();     // PHP массив
(string) $result;       // JSON через __toString
```

Доступные опции
---------------

[](#доступные-опции)

ОпцияТипОписание`targetPath``string`Каталог для сохранения`allowedMimeTypes``array`Разрешённые MIME-типы`maxFileSize``int`Максимальный размер (байты)`minFileSize``int`Минимальный размер (байты)`filenameGenerator``callable`Генератор имени файла `fn(string $name, array $file): string``throwExceptions``bool`Бросать `FileUploadException` вместо возврата ошибки`validators``array`Массив callable-валидаторов`targetMimeType``string`Целевой MIME-тип для конверсии`targetImageQuality``int`Качество конверсии (0-100)`locale``string`Локаль для сообщений ошибок (`'ru'` или `'en'`)Вспомогательные классы
----------------------

[](#вспомогательные-классы)

Все вспомогательные классы находятся в неймспейсе `Arris\Toolkit\FileUpload\*`.

### ImageConvertor

[](#imageconvertor)

Конвертирует изображения между форматами (GD). Fluent API:

```
use Arris\Toolkit\FileUpload\ImageConvertor;

ImageConvertor::from('/path/to/photo.jpg')
    ->toWebP(quality: 85)
    ->save('/path/to/output/');

ImageConvertor::from('/path/to/photo.jpg')
    ->toPng(compression: 9)
    ->save('/path/to/output/');

ImageConvertor::from('/path/to/photo.gif')
    ->toPng(preserveAlpha: true)
    ->save('/path/to/output/');
```

Поддерживаемые конверсии: JPEG, PNG, GIF, WebP, BMP → JPEG/PNG/GIF/WebP.

### MediaProbe

[](#mediaprobe)

Обёртка над `ffprobe` для получения метаданных медиафайлов:

```
use Arris\Toolkit\FileUpload\MediaProbe;

$info = MediaProbe::probe('/path/to/video.mp4');

echo $info->width;     // 1920
echo $info->height;    // 1080
echo $info->codec;     // "h264"
echo $info->duration;  // 125.4
echo $info->isVideo;   // true
echo $info->isAudio;   // false
```

Возвращает `MediaProbeResult` (readonly value object) или `null` при ошибке.

### Helper

[](#helper)

Статический хелпер для работы с размерами файлов и лимитами загрузки:

```
use Arris\Toolkit\FileUpload\Helper;

// Конвертация строкового размера в байты
Helper::returnBytes('64M');    // 67108864
Helper::returnBytes('1.5G');   // 1610612736
Helper::returnBytes('1024K');  // 1048576
Helper::returnBytes(1024);     // 1024

// Значение php.ini директивы в байтах
Helper::getIniValue('upload_max_filesize');  // например 20971520 (20M)
Helper::getIniValue('post_max_size');        // например 8388608 (8M)

// Вычисление реального лимита загрузки
$limits = Helper::getUploadLimits('64M');

// $limits['POST_MAX_SIZE']   — post_max_size в байтах
// $limits['UPLOAD_MAX_SIZE'] — upload_max_filesize в байтах
// $limits['CONFIG_MAX_SIZE'] — прикладной лимит (64M) в байтах
// $limits['REAL_MAX_SIZE']   — минимум из трёх
// $limits['IS_WRONG_SIZE']   — true если конфиг превышает физические лимиты
```

Лицензия
--------

[](#лицензия)

MIT License

###  Health Score

29

—

LowBetter than 57% of packages

Maintenance52

Moderate activity, may be stable

Popularity9

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity40

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~175 days

Total

5

Last Release

36d ago

PHP version history (2 changes)0.1.0PHP &gt;=7.4 | 8.\*

0.1.1PHP ^8.2

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/2164874?v=4)[Karel Wintersky](/maintainers/KarelWintersky)[@KarelWintersky](https://github.com/KarelWintersky)

---

Top Contributors

[![KarelWintersky](https://avatars.githubusercontent.com/u/2164874?v=4)](https://github.com/KarelWintersky "KarelWintersky (1 commits)")

---

Tags

validationimageconversionfileupload

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/karelwintersky-arrisphp-file-upload/health.svg)

```
[![Health](https://phpackages.com/badges/karelwintersky-arrisphp-file-upload/health.svg)](https://phpackages.com/packages/karelwintersky-arrisphp-file-upload)
```

###  Alternatives

[itskodinger/midia

Simple Media manager for your Laravel project

1416.1k](/packages/itskodinger-midia)[liyunfang/yii2-upload-behavior

Upload behavior for Yii 2

161.7k](/packages/liyunfang-yii2-upload-behavior)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
