Валидация файла

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Аватара пользователя
webplus
Сообщения: 336
Зарегистрирован: 2012.02.24, 22:05

Валидация файла

Сообщение webplus »

Здравствуйте!
Есть экшен:

Код: Выделить всё

    public function actionProfile()
    {

        $model = Profile();

        if ($model->load(\Yii::$app->request->post())) {
            $model->egrFile = UploadedFile::getInstance($model, 'egrFile');
            if ($model->uploadEgr() && $model->save()) {
                \Yii::$app->getSession()->setFlash('success', \Yii::t('user', 'Your profile has been updated'));
                return $this->refresh();
            }
        }
        return $this->render('profile', [
            'model' => $model,
        ]);
    }
есть модель:

Код: Выделить всё

class Profile extends ActiveRecord
{
    public $egrFile;
    public $imageFile;

    public static function tableName()
    {
        return '{{%profile}}';
    }


    public function uploadEgr()
    {
        if($this->validate()) {
            if (!empty($this->egrFile)) {
                @unlink(Yii::getAlias('@frontend/web/uploads/employer/egr/' . $this->file_egr));
                $this->file_egr = time() . '_' . rand(1, 1000) . '.' . $this->egrFile->extension;
                $this->egrFile->saveAs(Yii::getAlias('@frontend/web/uploads/employer/egr/' . $this->file_egr));
                $this->egrFile = Yii::getAlias('@frontend/web/uploads/employer/egr/' . $this->file_egr);
            }
            return true;
        }else {
            return false;
        }
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            ['company_name', 'string', 'max' => 255],
            ['address', 'string', 'max' => 255],
            ['phone', 'string', 'max' => 55],
            [['imageFile'], 'file', 'extensions' => 'gif, jpg, jpeg, png, txt', 'skipOnEmpty' => true],
            [['egrFile'], 'file', 'skipOnEmpty' => true, 'extensions' => 'jpg, jpeg, gif, doc, docx, rtf, odt, pdf, txt'],
            ['body', 'string'],
        ];
    }


}
В rules стоит разрешение на загрузку файлов с расширением 'jpg, jpeg, gif, doc, docx, rtf, odt, pdf, txt' , а по факту мне разрешает загружать только jpg. Если пытаюсь загрузить txt то ошибка валидации. Но ведь в правилах у меня то есть txt
Сайт по работе в Украине: https://jobis.com.ua/. Сайт по поиску строителей: https://stroyzakaz.com.ua/
Создание сайтов в Киеве: https://webplus.com.ua/ по доступной цене.
urichalex
Сообщения: 994
Зарегистрирован: 2015.08.07, 11:03

Re: Валидация файла

Сообщение urichalex »

Прпробуй 'checkExtensionByMimeType' => false
Аватара пользователя
Alexum
Сообщения: 683
Зарегистрирован: 2016.09.26, 10:00

Re: Валидация файла

Сообщение Alexum »

Если хотите минимум защиты, то лучше задать типы вручную. Использование только checkExtensionByMimeType => false отключает проверку вообще.

Н-р:

Код: Выделить всё

[['file'],'file', 'extensions' => ['xlsx','xls'],'checkExtensionByMimeType' => false, 'mimeTypes' => ['application/vnd.ms-office','application/vnd.ms-excel','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']],
и убедитесь, что у вас включено расширение в php.ini
extension=php_fileinfo.dll
Аватара пользователя
leonidps
Сообщения: 268
Зарегистрирован: 2011.01.18, 19:40
Откуда: Псков

Re: Валидация файла

Сообщение leonidps »

Такие же проблемы с валидацией, конкретно с файлами file_name.xlsx
здесь курил
viewtopic.php?f=29&t=23110&hilit=xlsx

открываю свойства до отправки(Linux Mint 18.1 Serena)
Электронная таблица (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)
решил посмотреть что с файлом после загрузки
отправляю, читаю

Код: Выделить всё

            $model->imageFile = UploadedFile::getInstance($model, 'imageFile');
            $fileMimeType = FileHelper::getMimeType($model->imageFile->tempName);
            var_dump($fileMimeType);
получаю
string(24) "application/octet-stream"
Разумеется, валидация провалена.
На всякий случай заглянул в инфо

Код: Выделить всё

fileinfo
fileinfo support 	enabled
version 	1.0.5
libmagic 	522 
Как решать?
Правила существуют не только для того, чтобы их нарушать.
Аватара пользователя
leonidps
Сообщения: 268
Зарегистрирован: 2011.01.18, 19:40
Откуда: Псков

Re: Валидация файла

Сообщение leonidps »

Попытаюсь дать развитие темы, поскольку периодически поднимается
Смотрим букварьhttp://php.net/manual/ru/features.file- ... method.php
Можно усмотреть, что для проверки файла предлагается использовать информацию из массива $_FILES
Смотрим исходники https://github.com/yiisoft/yii2/blob/ma ... r.php#L478
для проверки(Checks the mimeType of the $file against the list in the [[mimeTypes]] property) используется информация о файле в директории сервера для временных файлов.

Код: Выделить всё

$fileMimeType = FileHelper::getMimeType($file->tempName);
Предыдущий пост убедительно показывает что информация о файле из массива $_FILES и информация о временном файле из директории сервера это не одно и то же. Шансы при этом на успешную валидацию минимальны.
Решил переопределить валидатор стем чтобы пользовать для валидации сведения из массива $_FILES

Код: Выделить всё

class MyFileValidator extends FileValidator {
    protected function validateMimeType($file)
    {
        $fileMimeType = $file->type;
        foreach ($this->mimeTypes as $mimeType) {
            if ($mimeType === $fileMimeType) {
                return true;
            }
            if (strpos($mimeType, '*') !== false && preg_match($this->buildMimeTypeRegexp($mimeType), $fileMimeType)) {
                return true;
            }
        }
        return false;
    }
}
теперь валидация

Код: Выделить всё

        $rules_array[]=[['imageFile'], MyFileValidator::className(), 
            'extensions' => ['xlsx'],
            'checkExtensionByMimeType' => false, 
            'skipOnEmpty' => FALSE,
            'mimeTypes' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']
            ];
        return $rules_array;
выполняется успешно.
Насколько такое решение корректно и безопасно - это вопрос.
Правила существуют не только для того, чтобы их нарушать.
Ответить