src/FileHelper.php
public static function saveFiles(array $files): array
    {
        $saveFile = static function (array &$file, string &$uploadPath, int &$index = -1): ?array
        {
            if ($index >= 0) {
                $fn = &$file['name'][$index];
                $tn = &$file['tmp_name'][$index];
                $fe = &$file['error'][$index];
            } else {
                $fn = &$file['name'];
                $tn = &$file['tmp_name'];
                $fe = &$file['error'];
            }

            switch ($fe) {
                case UPLOAD_ERR_OK:
                    break;

                case UPLOAD_ERR_NO_FILE:
                    return null;

                case UPLOAD_ERR_INI_SIZE:
                    throw new FileSaveException(
                        'Размер принятого файла превысил максимально допустимый '
                        . 'размер, который задан директивой upload_max_filesize конфигурационного файла php.ini',
                        413
                    );

                case UPLOAD_ERR_FORM_SIZE:
                    throw new FileSaveException('Размер загружаемого файла превысил значение MAX_FILE_SIZE, '
                    . 'указанное в HTML-форме', 413);

                case UPLOAD_ERR_PARTIAL:
                    throw new FileSaveException('Загружаемый файл был получен только частично', 400);

                case UPLOAD_ERR_NO_TMP_DIR:
                    throw new FileSaveException('Отсутствует временная папка', 500);

                case UPLOAD_ERR_CANT_WRITE:
                    throw new FileSaveException('Не удалось записать файл на диск', 500);

                case UPLOAD_ERR_EXTENSION:
                    throw new FileSaveException('PHP-расширение остановило загрузку файла', 500);
            }

            $nameArray = explode('.', $fn);
            $ext = strtolower(end($nameArray));
            $newName = preg_replace(
                '/[\s,\/:;\?!*&^%#@$|<>~`]/',
                '',
                str_replace(
                    ' ',
                    '_',
                    str_replace($ext, '', $fn) . microtime(true)
                )
            );

            $fileMaxSizeMb = (int)(get_env('FILE_UPLOAD_MAX_SIZE') ?? static::FILE_UPLOAD_MAX_SIZE);

            if (!is_uploaded_file($tn)) {
                unlink($tn);
                throw new FileSaveException('Не удалось записать файл на диск', 500);
            }

            if (filesize($tn) > (1048576 * (int) $fileMaxSizeMb)) {
                unlink($tn);
                throw new FileSaveException(
                    "Размер загружаемого файла не может быть больше значения $fileMaxSizeMb мегабайт).", 413
                );
            }

            if (!($validExt = static::validateFileMimeType($tn))) {
                unlink($tn);
                throw new FileSaveException('Неподдерживаемый тип файла', 415);
            }

            if ($validExt !== $ext) {
                $ext = $validExt;
            }

            $newName = "$newName.$ext";
            $path = $uploadPath . $newName;
            if (!move_uploaded_file($tn, $path)) {
                throw new FileSaveException("Файл $fn не был корректно сохранен", 500);
            }

            $path = strtr($path, [$_SERVER['DOCUMENT_ROOT'] => '', static::getFilesDirectoryPath() => '']);
            return ['name' => $fn, 'path' => $path];
        };

        $result = [];
        foreach ($files as $field => &$file) {
            $filePath = static::getFilePath($field);
            $uploadPath = $_SERVER['DOCUMENT_ROOT'] . $filePath . '/';
            if (\is_array($file['name'])) {
                foreach ($file['name'] as $index => &$fn) {
                    if ($moveFile = $saveFile($file, $uploadPath, $index)) {
                        $result[$field][] = $moveFile;
                    }
                }

                unset($fn);
            } elseif ($moveFile = $saveFile($file, $uploadPath)) {
                $result[$field][0] = $moveFile;
            }
        }

        unset($file);
        return $result;
    }
public static function saveFiles(array $files): array
    {
        $saveFile = static function (array &$file, string &$uploadPath, int &$index = -1): ?array
        {
            if ($index >= 0) {
                $fn = &$file['name'][$index];
                $tn = &$file['tmp_name'][$index];
                $fe = &$file['error'][$index];
            } else {
                $fn = &$file['name'];
                $tn = &$file['tmp_name'];
                $fe = &$file['error'];
            }

            switch ($fe) {
                case UPLOAD_ERR_OK:
                    break;

                case UPLOAD_ERR_NO_FILE:
                    return null;

                case UPLOAD_ERR_INI_SIZE:
                    throw new FileSaveException(
                        'Размер принятого файла превысил максимально допустимый '
                        . 'размер, который задан директивой upload_max_filesize конфигурационного файла php.ini',
                        413
                    );

                case UPLOAD_ERR_FORM_SIZE:
                    throw new FileSaveException('Размер загружаемого файла превысил значение MAX_FILE_SIZE, '
                    . 'указанное в HTML-форме', 413);

                case UPLOAD_ERR_PARTIAL:
                    throw new FileSaveException('Загружаемый файл был получен только частично', 400);

                case UPLOAD_ERR_NO_TMP_DIR:
                    throw new FileSaveException('Отсутствует временная папка', 500);

                case UPLOAD_ERR_CANT_WRITE:
                    throw new FileSaveException('Не удалось записать файл на диск', 500);

                case UPLOAD_ERR_EXTENSION:
                    throw new FileSaveException('PHP-расширение остановило загрузку файла', 500);
            }

            $nameArray = explode('.', $fn);
            $ext = strtolower(end($nameArray));
            $newName = preg_replace(
                '/[\s,\/:;\?!*&^%#@$|<>~`]/',
                '',
                str_replace(
                    ' ',
                    '_',
                    str_replace($ext, '', $fn) . microtime(true)
                )
            );

            $fileMaxSizeMb = (int)(get_env('FILE_UPLOAD_MAX_SIZE') ?? static::FILE_UPLOAD_MAX_SIZE);

            if (!is_uploaded_file($tn)) {
                unlink($tn);
                throw new FileSaveException('Не удалось записать файл на диск', 500);
            }

            if (filesize($tn) > (1048576 * (int) $fileMaxSizeMb)) {
                unlink($tn);
                throw new FileSaveException(
                    "Размер загружаемого файла не может быть больше значения $fileMaxSizeMb мегабайт).", 413
                );
            }

            if (!($validExt = static::validateFileMimeType($tn))) {
                unlink($tn);
                throw new FileSaveException('Неподдерживаемый тип файла', 415);
            }

            if ($validExt !== $ext) {
                $ext = $validExt;
            }

            $newName = "$newName.$ext";
            $path = $uploadPath . $newName;
            if (!move_uploaded_file($tn, $path)) {
                throw new FileSaveException("Файл $fn не был корректно сохранен", 500);
            }

            $path = strtr($path, [$_SERVER['DOCUMENT_ROOT'] => '', static::getFilesDirectoryPath() => '']);
            return ['name' => $fn, 'path' => $path];
        };

        $result = [];
        foreach ($files as $field => &$file) {
            $filePath = static::getFilePath($field);
            $uploadPath = $_SERVER['DOCUMENT_ROOT'] . $filePath . '/';
            if (\is_array($file['name'])) {
                foreach ($file['name'] as $index => &$fn) {
                    if ($moveFile = $saveFile($file, $uploadPath, $index)) {
                        $result[$field][] = $moveFile;
                    }
                }

                unset($fn);
            } elseif ($moveFile = $saveFile($file, $uploadPath)) {
                $result[$field][0] = $moveFile;
            }
        }

        unset($file);
        return $result;
    }
Функция загрузки массива файлов на сервер

@param array $files - массив файлов, которые прислала форма и мета-информация о них

@return array

@throws Exceptions\HelperException
@throws FileUploadException