Yii Framework Forum: Yii User File Upload Problem - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Yii User File Upload Problem Rate Topic: -----

#1 User is offline   Shawn Morgan 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 6
  • Joined: 27-April 12

Posted 03 May 2012 - 12:52 PM

I'm using the Yii-User extension and trying to use the file upload widget. It doesn't upload the file no matter what I try. It updates the filename to the database, but for some reason it is apparently failing validation. The code in UWfile that is failing is this:

public function setAttributes($value,$model,$field_varname) {
....
if ($model->validate()) {
if ($old_file&&file_exists($old_file))
unlink($old_file);
$value->saveAs($file_name);
}
$value = $file_name;
} else {

The $model->validate() call is failing, but I have no idea why. I'm not including any additional validation on this field, and I'm not getting a flash of anything failing, it just skips the code where it saves the file.

Any help here?

Shawn
0

#2 User is offline   enotirab 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 45
  • Joined: 14-January 11

Posted 09 May 2012 - 05:08 PM

If the model is failing validation one of the easiest ways to see why is to just print out a list of all the errors for that model.

if($model->validate())
{
...
}else
print_r($model->errors);


I wouldn't use this in practice of course but for debugging its a quick way to see what issues you're running into.

Also, just a shot in the dark but make sure that your upload field for your file is marked as 'safe' in the model. I ran into this problem myself.
0

#3 User is offline   ametad 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 78
  • Joined: 08-February 12
  • Location:Holland

Posted 17 October 2012 - 10:21 AM

Almost the same thing I encounter... Hopefully someone can help me?

In a profile made with the yii-user module, I added a file upload field that uses the UWfile widget. This field is set 'Required: No, but show on registration form'.

When a user registers an account and NOT upload a file, everything is ok. Also when the user logs in and then update the profile with a file upload, this works perfectly.

The problem is that when a 'guest' fills out the registration form and tries to upload a file, no error is given but the file is NOT written to disk (nowhere found on the system!). But the path/to/the/file is indeed updated in the database.

Is this perhaps intended behaviour or is this a bug? Does anyone has a solution?

I will have a look to the validation rules more closely, thank you for pointing that out enotirab.

Greetings,
Ametad
0

#4 User is offline   Shawn Morgan 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 6
  • Joined: 27-April 12

Posted 17 October 2012 - 10:37 AM

I did find my problem, which had to do with PHP's settings for maximum file size. What was happening is that PHP wasn't allowing the file upload because of php.ini's upload_max_filesize setting, which was 2M on php.ini, but the file was 5M.

Shawn
0

#5 User is offline   ametad 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 78
  • Joined: 08-February 12
  • Location:Holland

Posted 18 October 2012 - 06:02 AM

Shawn,

Have you also tried to upload a file on a blank registration? In my case the upload works fine when logged in, when the user or admin edits the profile with a file upload.
0

#6 User is offline   ametad 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 78
  • Joined: 08-February 12
  • Location:Holland

Posted 18 October 2012 - 10:23 AM

I think I understand why it is not working... Because the model is not filled with values YET, it will never validate.. I think the file only needs to be written to disk 'onAfterSave'! I mean, then the whole model is indeed validated and the CUploadedFile can be safely written down.

But how is this possible..?

(I have to go now, but I'll be back!)
0

#7 User is offline   ametad 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 78
  • Joined: 08-February 12
  • Location:Holland

Posted 22 October 2012 - 03:52 AM

After the last post I have still no solution.. I will try to describe the problem a little better. Hopefully someone can give me a tip on how to proceed.

On the registration form I put (among other fields) a VARCHAR field with the UWfile widget. As described earlier the problem does NOT occur with an existing profile. The problem is that the file not is written to disk, but the path/to/file stored in the database.

A simple test added to the UWfile.php (look for the print_r() as proposed by enotirab)
public function setAttributes($value,$model,$field_varname) {
        $value = CUploadedFile::getInstance($model,$field_varname);
        
        if ($value) {
            $old_file = $model->getAttribute($field_varname);
            $file_name = $this->params['path'].'/'.$value->name;
            if (file_exists($file_name)) {
                $file_name = str_replace('.'.$value->extensionName,'-'.time().'.'.$value->extensionName,$file_name);
            }
            if ($model->validate()) {
                if ($old_file&&file_exists($old_file))
                    unlink($old_file);
                $value->saveAs($file_name);
            } else { //TEST
                print_r($model->getErrors());
                Yii::app()->end();
            }
            $value = $file_name;
        } else {
            if (isset($_POST[get_class($model)]['uwfdel'][$field_varname])&&$_POST[get_class($model)]['uwfdel'][$field_varname]) {
                $old_file = $model->getAttribute($field_varname);
                if ($old_file&&file_exists($old_file))
                    unlink($old_file);
                $value='';
            } else {
                $value = $model->getAttribute($field_varname);
            }
        }
        return $value;
    }

When I fill out the form this is the output:
Array ( [firstname] => Array ( [0] => First Name cannot be blank. ) [lastname] => Array ( [0] => Last Name cannot be blank. ) [gender] => Array ( [0] => Gender cannot be blank. ) [city] => Array ( [0] => City cannot be blank. ) [birthday] => Array ( [0] => Birthday cannot be blank. ) [phone] => Array ( [0] => Phone number cannot be blank. ) ) 


I don't understand why the model is not validated, can anyone explain this to me? I have filled it out correctly of course.
0

#8 User is offline   ametad 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 78
  • Joined: 08-February 12
  • Location:Holland

Posted 29 October 2012 - 04:49 PM

If anyone ever is interested, here is my solution:

<?php

class UWfile {
    
    /**
     * @var array
     * @name widget parametrs
     */
    public $params = array('path'=>'assets');
    
    private $_file_instance = NULL;
    private $_old_file_path = '';
    private $_new_file_path = '';
    
    /**
     * Widget initialization
     * @return array
     */
    public function init() {
        return array(
            'name'=>__CLASS__,
            'label'=>UserModule::t('File field'),
            'fieldType'=>array('VARCHAR'),
            'params'=>$this->params,
            'paramsLabels' => array(
                'path'=>UserModule::t('Upload path'),
            ),
            'other_validator'=>array(
                'file'=>array(
                    'allowEmpty'=>array('','false','true'),
                    'maxFiles'=>'',
                    'maxSize'=>'',
                    'minSize'=>'',
                    'tooLarge'=>'',
                    'tooMany'=>'',
                    'tooSmall'=>'',
                    'types'=>'',
                    'wrongType'=>'',
                    'safe'=>array('true','false'),
                ),
            ),
        );
    }
    
    /**
     * @param $value
     * @param $model
     * @param $field_varname
     * @return string
     */
    public function setAttributes($value,$model,$field_varname) {
        $this->_new_file_path = $this->_old_file_path = $model->getAttribute($field_varname);
        
        if ($this->_file_instance = CUploadedFile::getInstance($model,$field_varname)){
            
            $model->getEventHandlers('onAfterSave')->insertAt(0,array($this, 'processFile'));
            $file_name = str_replace(' ', '-', $this->_file_instance->name);
            $this->_new_file_path = $this->params['path'].'/';
            
            if ($this->_old_file_path){
                $this->_new_file_path = pathinfo($this->_old_file_path, PATHINFO_DIRNAME).'/';
            } else {
                $this->_new_file_path .= $this->unique_dir($this->_new_file_path).'/';
            }
            
            $this->_new_file_path .= $file_name;
            
        } else {
            if (isset($_POST[get_class($model)]['uwfdel'][$field_varname])&&$_POST[get_class($model)]['uwfdel'][$field_varname]){
                $model->onAfterSave = array($this, 'processFile');
                $path = '';
            }
        }
        
        return $this->_new_file_path;
    }
        
    /**
     * @param $value
     * @return string
     */
    public function viewAttribute($model,$field) {
        $file = $model->getAttribute($field->varname);
        if ($file) {
            $file = Yii::app()->baseUrl.'/'.$file;
            return CHtml::link(pathinfo($file, PATHINFO_FILENAME),$file);
        } else
            return '';
    }
        
    /**
     * @param $value
     * @return string
     */
    public function editAttribute($model,$field,$params=array()) {
        if (!isset($params['options'])) $params['options'] = array();
        $options = $params['options'];
        unset($params['options']);
        
        return CHtml::activeFileField($model,$field->varname,$params)
        .(($model->getAttribute($field->varname))?'<br/>'.CHtml::activeCheckBox($model,'[uwfdel]'.$field->varname,$params)
        .' '.CHtml::activeLabelEx($model,'[uwfdel]'.$field->varname,array('label'=>UserModule::t('Delete file'),'style'=>'display:inline;')):'')
        ;
    }
    
    public function processFile($event){
            
        $model = $event->sender;
        
        if ($this->_old_file_path && file_exists($this->_old_file_path)){
            unlink($this->_old_file_path);
            $files = scandir(pathinfo($this->_old_file_path, PATHINFO_DIRNAME));
            if (empty($files[2])){
                //No files in directory left
                rmdir(pathinfo($this->_old_file_path, PATHINFO_DIRNAME));
            }
            
        }
        if ($this->_file_instance){
            if (!is_dir(pathinfo($this->_new_file_path, PATHINFO_DIRNAME))){
                mkdir(pathinfo($this->_new_file_path, PATHINFO_DIRNAME), 0777, TRUE);
            }
            $this->_file_instance->saveAs($this->_new_file_path);
        }
    }
    
    private function unique_dir($base_path='')
    {
        $unique_dir = $this->random_string();
        
        while (is_dir($base_path . $unique_dir)) {
            $unique_dir = $this->random_string();
        }
        
        return $unique_dir;
    }
    
    private function random_string($max = 20){
        $string = '';
        $chars = "abcdefghijklmnopqrstuvwxwz0123456789_-ABCDEGFHIJKLMNOPQRSTUVW";
        for($i = 0; $i < $max; $i++){
            $rand_key = mt_rand(0, strlen($chars));
            $string  .= substr($chars, $rand_key, 1);
        }
        return str_shuffle($string);
    }
    
}

0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users