Cfilevalidator $Maxsize Problem (File Uploads Despite Size Limit Error)

hi, I’m uploading multiple files using model attribute and everything works fine despite the $maxSize limit set in validator for model attribute. When I try to upload file larger tham 5M (it is my $maxSize) I get and error in form but upload completes successfully.

This is attribute rule:


array('uploadedAttachments', 'file', 'types'=>'txt,doc,zip', 'maxSize'=>Utils::returnBytes('5M'), 'maxFiles'=>10, 'allowEmpty'=>true),

This is the widget configuration in form:


<?php $this->widget('CMultiFileUpload', array(

	'model'=>$model,

	'attribute'=>'uploadedAttachments',

        'accept'=>'txt,doc,zip',

	'remove'=>'',

	'file'=>'<em>$file</em> <a class="MultiFile-remove" href="#Page_files_new_wrap" onclick="$(this).parent().prev().click()">Remove</a>',

	'max'=>10,

)); ?>

<?php echo $form->error($model,'uploadedAttachments'); ?>

and this is the part of controller action that saves the model:




...

$model->uploadedAttachments = CUploadedFile::getInstances($model, 'uploadedAttachments');

$model->save();

foreach($model->uploadedAttachments as $key => $file)

{

	FB::log($file->error); // shows no error

	$file->saveAs($my_file_path)

}

...



Am I doing something wrong? Please help.

I think you want this:




if ($model->save())

{

    foreach($model->uploadedAttachments as $key => $file)

    {

        $file->saveAs($file_path)

    }

}




Sorry for my bad:


...

FB::log($file->error, 'error');

FB::log($file->hasError, 'hasError');



actually returns error id and if error occured. I don’t know what I was thinking about…

I’ll simply check $file->error before save and that sould do the trick for me.

I think the only way you’ll manage that is to create a model purely for validating a single file, then iterate through each file and assign each to an instance of the model.

Generally you want the whole update to fail if any part of it fails, which is why you’re struggling to get this to work in the way you’d like.

Pseudocodish example:




    $files = getTheFilesHereSomehow();


    foreach ($files as $file)

    {

        $fvm = new FileVerificationModel;

        $fvm->file = $file;

        if ($fvm->validate())

            $file->saveAs($filePath);

    }



Edit: Removed strikethrough.

Actually there was something strange going on when I chacked my code on another computer I didn’t get any specific file errors. After some research I found that I had “upload_max_filesize” in php.ini set to 30M and my maxSize was set to 5M it effected that size error was shown and file had no errors. It seems that “upload_max_filesize” in php.ini and “maxSize” in rules must be the same.

I don’t think they need to be the same. You’re dealing with two separate sources of error; one from PHP’s file upload and one from model validation. I suspect that $file->error only shows the PHP file errors, not model errors. See if the code I struck-through above helps.

I’m sure that upload_max_filesize and maxSize don’t need to be the same. As far as I know, upload_max_filesize represents the maximum total size of all uploaded files, while maxSize is the maximum size of each individual file. In combination, they allow you to control both the total amount of data uploaded and the size of each file.

I totally agree with you but that’s the only way I can get error info for specific file.

I could check for file upload attribute errors and skip saving all files but I want to save files that are ok. That’s why I want to get validation info about specific file and if there are any errors skip that file only.

Now (“upload_max_filesize” set to “30M” and “maxSize” set to “5M”) I can’t get specific file validation info :(.

Check out my crossed-out code above and see if that solution helps. I’ll remove the crossing out if so.

Cross is a weird word if you type it too many times…

Cross. Cross.

What’s that model “FileVerificationModel”?

You’d need to create it as a separate model for the purposes of file verification. I’ll remove the crossing out above as the post may be relevant.

I see, it gave me some idea how to check file size. Do you know if there is a way to get specific model attribute validation rule? If I will achieve that I can’t simply check if $file->size > file_validator_max_size.

I think it also can be done by creating na instance of CFileValidator and testing each file but it would be great to use the same setting as it is set in the model.

This does the job:


foreach(Page::model()->getValidators('uploadedAttachments') as $validator)

{

	if($validator instanceof CFileValidator)

	{

		FB::log($file->size > $validator->maxSize);

	}

}

it checks if the current file size is grater than size limit set for file validator. But I don’t know if is the best solution?

Now I’ve found another problem. File type for multiple file upload also isn’t being included in error info for specific file. It looks like the only way to control file save is to check summary error for all files if there is one. I haven’t found any simple way to check validation of each file :(.

Again, you’d have to do what I suggested and put all of the relevant file validation rules into a separate model, then instantiate and validate one for every file. I can’t think of a better way to handle your particular situation.

Ok, I think I’ll do it as you suggested at the very begining to save files after $model->save() returns true as my target upload behaviour isn’t supported by yii.

Thanks for help Keith.