承接 karelwintersky/arris.php-file-upload 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

karelwintersky/arris.php-file-upload

Composer 安装命令:

composer require karelwintersky/arris.php-file-upload

包简介

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

README 文档

README

Библиотека для загрузки файлов с валидацией, конвертацией изображений и 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() — проверка первичной загрузки

Проверяет 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() — конверсия, сохранение

Если 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()

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

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

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

  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)

// 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);
});

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

Формат Источник Цель
JPEG yes yes
PNG yes yes
GIF yes yes
WebP yes yes
BMP yes

Система ошибок

Коды ошибок

Каждая ошибка имеет код 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)

Встроенные 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

Объект возвращаемый 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

Конвертирует изображения между форматами (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

Обёртка над 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

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

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

karelwintersky/arris.php-file-upload 适用场景与选型建议

karelwintersky/arris.php-file-upload 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 07 月 13 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「image」 「file」 「upload」 「validation」 「conversion」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 karelwintersky/arris.php-file-upload 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 karelwintersky/arris.php-file-upload 我们能提供哪些服务?
定制开发 / 二次开发

基于 karelwintersky/arris.php-file-upload 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 1
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 11
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-07-13