CFileValidator with SWFUpload

How are you supposed to use CFileValidator with SWFUpload? I’m struggling because SWFUpload does not render a file ‘input’ field - so there is no field name to specify for validation!

It is just a Flash control which passes the filedata into a POST which I retrive via:

CUploadedFile::getInstanceByName(‘Filedata’);

So how do I perform validation on the uploaded file?

Cheers G,

Didn’t my code showed you how? Check the following:





                       $picture_file = CUploadedFile::getInstanceByName('Filedata');

			

		       // .... some code is here

			

                        // validating the picture

			$result = Picture::validateUploadedPicture($picture_file,1480,1240,240,180,array('image/jpeg','image/gif','image/png'));

						

			switch($result){

				case Picture::MAX_HEIGHT_ERROR:

					throw new Exception('Maximum allowed height is 1240px');

					break;

				case Picture::MAX_WIDTH_ERROR:

					throw new Exception('Maximum allowed width is 1480px');

					break;

				case Picture::MIN_HEIGHT_ERROR:

					throw new Exception('Minimum allowed height is 240px');

					break;

				case Picture::MIN_WIDTH_ERROR:

					throw new Exception('Minimim allowed width is 180px');

					break;

				case Picture::MIME_TYPE_ERROR:

					throw new Exception('JPEG, GIF and PNG are the only MIME TYPES allowed');

					break;

				

			}




And the validatePicture has the following format:




public static function validateUploadedPicture( CUploadedFile $file, $maxWidth, $maxHeight, $minWidth, $minHeight, $mimeTypes ){

		

		$info = @getimagesize( $file->getTempName() );

		

		// remove unnecessary values from $info and make it more readable

		$info = array(

			'width' => $info[0],

			'height' => $info[1],

			'mime' => $info['mime'],

		);

		

		if ($info['width'] < $minWidth) {

			return self::MIN_WIDTH_ERROR;

		}

		if ($info['width'] > $maxWidth) {

			return self::MAX_WIDTH_ERROR;	

		}

		if ($info['height'] < $minHeight) {

			return self::MIN_HEIGHT_ERROR;

		}

		if ($info['height'] > $maxHeight) {

			return self::MAX_HEIGHT_ERROR;

		}

		

		$mimeTypes = is_scalar($mimeTypes) ? array($mimeTypes) : $mimeTypes;

		if (!in_array($info['mime'], $mimeTypes)) {

			return self::MIME_TYPE_ERROR;

		}

		return self::PICTURE_VALID;

		

}



Of course this is for validating just a picture, but you change your validation function to suit your file format specs.

Best

Thank Antonio. I must have overlooked that. This looks good - one thing seems to be missing from this though - how can we check for file size (bytes)?

Hi G,

Use filesize (http://php.net/manual/es/function.filesize.php)

$filesize = filesize( $file->getTempName() );

Cheers

Cheers. You should release this as an extension! ;)

I will give it a thought. There a couple around (as validators), but I’ll check what is the best way to implement. Last time (cleditor) wasn’t really the right approach, I dont want to make another pitfall again :)

Hi Antonio - your validation function is perfect! Thank you man.

I am just having a couple of issues though:

  1. Were you able to get the postParams working? No matter what I do I cannot get the upload action to retrieve my custom post params.

  2. Similarly, I can’t seem to use Yii::app->user->id in the upload action - it seems to be empty all the time. Everywhere else in my app it’s fine. This must have something to do with the ‘PHPSESSID’ variable that is passed in.

Oops! Forgot to mention G,

Yes I was able to get the parameters (check the UploadAction.php of the picture!)




// SEE PARAMETER NAME!

$newsId = Yii::app()->request->getParam('newsId');



  1. postParams — on the uploader view:




 $uurl = $this->createUrl('picture/upload',array('newsId'=>$newsId)); 

 $this->widget('application.widgets.CSwfUpload', array(

    'postParams'=>array('newsId'=>$newsId), //<---- SEE- HERE!

    'config'=>array(

        'use_query_string'=>false, //<-------------------------- query string to false

        'upload_url'=> CHtml::normalizeUrl($uurl), //Use $this->createUrl method or define yourself

// more settings ....



  1. — Put this at the end of you index.php file (bootstrap) -is a SWFUpload issue



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

{

  $_COOKIE['PHPSESSID'] = $_POST['PHPSESSID'];

}



Thanks Antonio. I will try again with the post parameters, for some reason I was not able to get it to work when I first tried it.

With regards to the session issue, I actually fixed that by referring to the sample PHP code provided by SWFUpload:


if(isset($_POST["PHPSESSID"]))

{

	session_id($_POST["PHPSESSID"]);

}

elseif(isset($_GET["PHPSESSID"]))

{

	session_id($_GET["PHPSESSID"]);

}

Is on the example project I forwarded to you G.

Cheers man

Cheers Antonio. Got a few last questions for you:

  1. Is it necessary to validate the filename, i.e. can CUploadedFile accept any characters in the filename, or will it fail if there are any unknown characters?

  2. Is it possible to ensure animated GIFs cannot be uploaded?

  3. Is it possible to generate thumbnails to have a MAX height, but keep a fixed width? At the moment I do this:

$thumbFactory->resize(200);

This ensures width is always 200px, but some of the images are tall and the thumbnails exceed the height of my container divs. I need all thumbnails to be 200px wide and height should be maximum 300px.

  1. Never had a problem with any characters on fails, nevertheless, if you look at my code I completely change its named by hashing it

  2. How to find out if it is animated GIF on the server (dont have a clue about client validation though)





function is_ani($filename) {

    if(!($fh = @fopen($filename, 'rb')))

        return false;

    $count = 0;

    //an animated gif contains multiple "frames", with each frame having a

    //header made up of:

    // * a static 4-byte sequence (\x00\x21\xF9\x04)

    // * 4 variable bytes

    // * a static 2-byte sequence (\x00\x2C)


    // We read through the file til we reach the end of the file, or we've found

    // at least 2 frame headers

    while(!feof($fh) && $count < 2)

        $chunk = fread($fh, 1024 * 100); //read 100kb at a time

        $count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00\x2C#s', $chunk, $matches);


    fclose($fh);

    return $count > 1;

}



  1. Use PhpThumbLibrary ( I think is in the code I sent you right?) My article: http://www.ramirezcobos.com/2010/10/15/how-to-use-phptumb-library-with-yii/