Problem With Cuploadedfile And Android Http Request

Hi,

i’m trying to upload a file named uploaded_file with an android http request.

My environment is:

MAMP 2.1.1 with PHP 5.4.4 and Mountain Lion 10.8.3, MySQL database UTF8

If i use move_uploaded_file, everything works fine, but i want to use CUploadedFile.

My model Media is


class Media extends CActiveRecord

{

	public $uploaded_file;

        .....


	public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array(

			array('Name, Title', 'length', 'max'=>500),

			array('CreatedAt, LastEdit, Filename', 'safe'),

			// The following rule is used by search().

			// Please remove those attributes that should not be searched.

			array('ID, CreatedAt, LastEdit, Name, Title, Filename', 'safe', 'on'=>'search'),

			array('uploaded_file', 'file', 'types'=>'jpg,jpeg,gif,png'),

		);

	}


        ...

}

and in the controller i have




public function actionUploadImage(){

...

$media = new Media;

$media->uploaded_file=CUploadedFile::getInstance($media,'uploaded_file');

...

}



but nothing is uploaded.

if i try




		error_log($media->uploaded_file);

		error_log($_FILES['uploaded_file']['name']);



i see the second one but the first is empty.

I’ve also tried to upload the file using a form




$form = $this->beginWidget(

'CActiveForm',

array(

'id' => 'upload-form',

'enableAjaxValidation' => false,

'htmlOptions' => array('enctype' => 'multipart/form-data'),

)

);

// ...

echo $form->labelEx($model, 'uno');

echo $form->fileField($model, 'uploaded_file');

echo $form->error($model, 'tre');

echo CHtml::submitButton('Carica');

$this->endWidget();



And it works.

Where am i wrong?

Thank you very much.

Giacomo

You need to call the saveAs method - http://qadrio.wordpress.com/2012/02/13/uploading-file-in-yii-using-cuploadedfile/

Matt

Hi, sorry, i forget to paste that line of code. i write all the function in the controller.




	public function actionUploadImage(){


		$target_path = "assets/uploads/";


		//Create Image


		$media = new Media;


		$media->uploaded_file=CUploadedFile::getInstance($media,'uploaded_file');


		error_log($media->uploaded_file);

		//error_log($_FILES['uploaded_file']['name']);


		if($media->save())

		{

			$newName = uniqid().'.'.$media->uploaded_file->getExtensionName();

			$media->uploaded_file->saveAs($target_path.$newName);


			$media->CreatedAt = new CDbExpression('NOW()');

			$media->LastEdit = new CDbExpression('NOW()');

			$media->Name = $newName;

			$media->Title = $media->uploaded_file->getName();

			$media->Filename = $target_path.$newName;

			$media->save();


		}


	}

[s]I haven’t tested it but try

[/s][list=1][]validating[]saving file[*]saving model[/list][s]

I’ve got a sneaking suspicion that after you save the model the first time, the uploaded_file property is being reset.

Matt[/s]

Nevermind, it should be OK.

Hi, thanks for the suggestion, but if i edit the code as follow




public function actionUploadImage(){


                $target_path = "assets/uploads/";


                //Create Image


                $media = new Media;


                $media->uploaded_file=CUploadedFile::getInstance($media,'uploaded_file');


                error_log($media->uploaded_file);

                //error_log($_FILES['uploaded_file']['name']);


                 $newName = uniqid().'.'.$media->uploaded_file->getExtensionName();

                $media->uploaded_file->saveAs($target_path.$newName);


                if($media->save())

                {

                        $media->CreatedAt = new CDbExpression('NOW()');

                        $media->LastEdit = new CDbExpression('NOW()');

                        $media->Name = $newName;

                        $media->Title = $media->uploaded_file->getName();

                        $media->Filename = $target_path.$newName;

                        $media->save();


                }


        }



It gave me the error


PHP Fatal error:  Call to a member function getExtensionName() on a non-object

The strange thing is that if i put the saveAs method inside the if($media->save()), i’ve got no error.

Is the code making it into the model’s save method or is the save failing? Also, you calling save twice, why? Can’t you just populate the model and save it once?

Try this





public function actionUploadImage()

{

	$target_path = "assets/uploads/";


	$model = new Media();

	

	if(isset($_POST['Media']))

	{

		$model->attributes=$_POST['Media']; // This is important

		$model->uploaded_file=CUploadedFile::getInstance($model, 'uploaded_file');

		

		$newName = uniqid().'.'.$model->uploaded_file->getExtensionName();

				

		$model->CreatedAt = new CDbExpression('NOW()');

		$model->LastEdit = new CDbExpression('NOW()');

		$model->Name = $newName;

		$model->Title = $model->uploaded_file->getName();

		$model->Filename = $target_path.$newName;

								

		if($model->save())

		{

			$model->uploaded_file->saveAs($target_path.$newName);

		}

	}

}

Matt

Hi, it’s still not working and i don’t understand why.

In this line




$media->uploaded_file=CUploadedFile::getInstance($media,'uploaded_file');



i suppose to pass $_FILES[‘uploaded_file’], right? But i got an empty instance, so the code not pass the $model->save() because of the line array(‘uploaded_file’, ‘file’, ‘types’=>‘jpg,jpeg,gif,png’) in




	public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array(

			array('Name', 'length', 'max'=>45),

			array('Title', 'length', 'max'=>255),

			array('Filename', 'length', 'max'=>555),

			// The following rule is used by search().

			// Please remove those attributes that should not be searched.

			array('ID, Name, Title, Filename', 'safe', 'on'=>'search'),

			array('uploaded_file', 'file', 'types'=>'jpg,jpeg,gif,png'), //cause of this line, the model not pass the save() validation

		);

	}



I really do not understand…

PHP’s $_FILES array contains the file but you need to populate your model so that the validation can do it’s work. What error message are you getting?

Matt

I get the




PHP Fatal error:  Call to a member function getExtensionName() on a non-object in ...



Maybe i’m passing something wrong from the device, but i don’t think so because if i use




move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $target_path1)



it works.

Hi Matt, i’ve finally solved the problem. Tomorrow i’ll post my solution. I’ve used the constructor of the cuploadedfile instead of the getinstance function.

Thanks for the hints.

Giacomo

Here’s the code that i’ve used:




$media->uploaded_file = new CUploadedFile($_FILES['uploaded_file']['name'], $_FILES['uploaded_file']['tmp_name'], $_FILES['uploaded_file']['type'], $_FILES['uploaded_file']['size'], $_FILES['uploaded_file']['error']);



and i i print the $_FILES i got




array(1) {

  ["uploaded_file"]=>

  array(5) {

    ["name"]=>

    string(23) "IMG_20130527_195229.jpg"

    ["type"]=>

    string(0) ""

    ["tmp_name"]=>

    string(36) "/Applications/MAMP/tmp/php/phpYURSUK"

    ["error"]=>

    int(0)

    ["size"]=>

    int(96382)

  }

}



Hope this will help someone.

Giacomo

Glad you figured it out, but you really shouldn’t have to do it that way. Post back if you find out why this was happening. Take care.

Matt