Search code examples
phpyii2mime-typesyii2-advanced-app

Yii2 How to modify file validator for new extension type?


I have file with extension .edoc and mimetype is application/zip. When I try to upload files with this extension, file validator gives me a standard error - that only given (in rules) extensions is possible to upload. Here is my rules:

return array_merge($parent_rules,[
            [
                ['file'],
                'file',
                'maxSize' => 5242880,  // limit 5mb => 5(mb) * 1024(kb) * 1024(b)

                'extensions' => ['pdf','doc','docx','xls','xlsx','png','jpeg','jpg','gif','tiff','tif','avi','flv',
                'wmv','mov','mp4','mkv','ogg','xml','zip','rar','7z','ods','odt','txt','edoc','msg'],
            ],
        ]);

I found that in vendor\yiisoft\yii2\helpers\mimeTypes.php there is an array of rules where extension ".edoc" is not described. When I added key=>value pair

'edoc' => 'application/zip'

File upload is working.

How/is its possible to modify or add this rule without modifying vendor files?


Solution

  • @Michal Hynčica in first answer gave me a good start for this problem, but for avoid load modified file in memory on every request in the sytem, I modified a little bit his code.

    So... I made my own magic file like Michal

    <?php
    // load mime types from original magic file
    $originalMagicFile = Yii::getAlias('@yii/helpers/mimeTypes.php');
    $mimeTypes = require $originalMagicFile;
    
    $mimeTypes['edoc'] => 'application/zip';
    return $mimeTypes;
    

    Then I created custom behavior class for this custom magic file

    class MimeTypesBehavior extends Behavior
    {
        public function events(): array
        {
            return [
                ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',
            ];
        }
    
        public function beforeValidate()
        {
            FileHelper::$mimeMagicFile = dirname(__DIR__, 2) .'/backend/models/edocMimeTypes.php';
        }
    
    }
    

    and added this behavior to my model form

    class FileForm extends File
    {
        public $file;
    
        public function behaviors(): array
        {
            return [
                MimeTypesBehavior::class,
            ];
        }
    
    
        /**
         * @return array the validation rules.
         */
        public function rules(): array
        {
            $parent_rules = parent::rules();
            return array_merge($parent_rules,[
                [
                    ['file'],
                    'file',
                    'maxSize' => 5242880,  //  limit 5mb => 5(mb) * 1024(kb) * 1024(b)
                    'extensions' => ['pdf','doc','docx','xls','xlsx','png','jpeg','jpg','gif','tiff','tif','avi','flv',
                        'wmv','mov','mp4','mkv','ogg','xml','zip','rar','7z','ods','odt','txt','edoc','msg']
                ],
            ]);
        }
    

    And everything works perfect.