My (mostly technical) blog

Enhanced: Image Upload Component for CakePHP 1.2

Posted on: July 18, 2008

UPDATE 2: Dear all, the code is now released under MIT license and is version controlled on github thanks to TuteC!

7/7/2009.

UPDATE: Please check this comment for a more updated example.

Component code updated on 30/4/2009, check the posted code or the download links.

I revisited the code I used to develop the old image resize component because I found a bug in the resize code. I used the resize function from the PImageComponent by Wendy and ended up with the current version I’m using at my websites:
Code download at the bottom of the post.

<?php
/*
 File: /app/controllers/components/image.php
*/
class ImageComponent extends Object
{
	/*
	*	Uploads an image and its thumbnail into $folderName/big and $folderName/small respectivley.
	* 	Also uploads a zoom cropped image into $folderName/home. You could easily modify it to suit your needs!
	
	* 	Directions:
	*	In view where you upload the image, make sure your form creation is similar to the following
	*	<?= $form->create('ControllerName',array('type' => 'file')); ?>
	

	*	In view where you upload the image, make sure that you have a file input similar to the following
	*	<?= $form->file('Image/image1'); ?>
	
	
	*	In the controller, add the component to your components array
	*	var $components = array("Image");
	

	*	In your controller action (the parameters are expained below)
	*	$image_path = $this->Image->upload_image_and_thumbnail($this->data,"name1", 573,380,80,80, "sets");
	*	this returns the file name of the result image.  You can  store this file name in the database
	*
	*	Note that your image will be stored in 3 locations:
	*	Image: /webroot/img/$folderName/big/$image_path 
	*	Thumbnail:  /webroot/img/$folderName/small/$image_path 
	*	Homepage:  /webroot/img/$folderName/home/$image_path  
	*
	*	You could easily add more locations or remove locations you don't need


	*	Finally in the view where you want to see the images
	*	<?= $html->image('sets/big/'.$furnitureSet['FurnitureSet']['image_path']);
	* 	where "sets" is the folder name we saved our pictures in, and $furnitureSet['FurnitureSet']['image_path'] is the file name we stored in the database
	

	*	Parameters:
	*	$data: the image data array from the form
	*	$maxw: the maximum width that you want your picture to be resized to
	*	$maxh: the maximum width that you want your picture to be resized to
	*	$thumbscalew: the maximum width hat you want your thumbnail to be resized to
	*	$thumbscaleh: the maximum height that you want your thumbnail to be resized to
	*	$folderName: the name of the parent folder of the images. The images will be stored to /webroot/img/$folderName/big/ and  /webroot/img/$folderName/small/
	*/	
	function upload_image_and_thumbnail($data, $maxw, $maxh, $thumbscalew, $thumbscaleh, $folderName) {
		if (strlen($data['name'])>4){ 
					$error = 0;
					$tempuploaddir = "img/temp"; // the /temp/ directory, should delete the image after we upload
					$homeuploaddir = "img/".$folderName."/home"; // the /home/ directory
					$biguploaddir = "img/".$folderName."/big"; // the /big/ directory
					$smalluploaddir = "img/".$folderName."/small"; // the /small/ directory for thumbnails
					
					// Make sure the required directories exist, and create them if necessary
					if(!is_dir($tempuploaddir)) mkdir($tempuploaddir,0755,true);
					if(!is_dir($homeuploaddir)) mkdir($homeuploaddir,0755,true);
					if(!is_dir($biguploaddir)) mkdir($biguploaddir,0755,true);
					if(!is_dir($smalluploaddir)) mkdir($smalluploaddir,0755,true);
					
					$filetype = $this->getFileExtension($data['name']);
					$filetype = strtolower($filetype);
 
					if (($filetype != "jpeg")  && ($filetype != "jpg") && ($filetype != "gif") && ($filetype != "png"))
					{
						// verify the extension
						return;
					}
					else
					{
						// Get the image size
						$imgsize = GetImageSize($data['tmp_name']);
					}

					// Generate a unique name for the image (from the timestamp)
					//$id_unic = str_replace(".", "", strtotime ("now"));
					$id_unic = $uuid = String::uuid();
					$filename = $id_unic;
					  
					settype($filename,"string");
					$filename.= ".";
					$filename.=$filetype;
					$tempfile = $tempuploaddir . "/$filename";
					$homefile = $homeuploaddir . "/$filename";
					$resizedfile = $biguploaddir . "/$filename";
					$croppedfile = $smalluploaddir . "/$filename";
					
					
					if (is_uploaded_file($data['tmp_name']))
                    {                    
						// Copy the image into the temporary directory
                        if (!copy($data['tmp_name'],"$tempfile"))
                        {
                            //print "Error Uploading File!.";
							unset($filename);
							unlink($tempfile);
                            exit(); 
                        }
						else {				
							/*
							 *	Generate the home page version of the image center cropped
							 */
							$this->resizeImage('resizeCrop', $tempuploaddir, $filename, $homeuploaddir, $filename, 886, 473, 85);
							/*
							 *	Generate the big version of the image with max of $imgscale in either directions
							 */
							$this->resizeImage('resize', $tempuploaddir, $filename, $biguploaddir, $filename, $maxw, $maxh, 85);							

							/*
							 *	Generate the small thumbnail version of the image with scale of $thumbscalew and $thumbscaleh
							 */
							$this->resizeImage('resizeCrop', $tempuploaddir, $filename, $smalluploaddir, $filename, $thumbscalew, $thumbscaleh, 75);
													
							// Delete the temporary image
							unlink($tempfile);
						}
                    }
 
                     // Image uploaded, return the file name
					 return $filename;   
		}
	}
	
	/*
	*	Deletes the image and its associated thumbnail
	*	Example in controller action:	$this->Image->delete_image("1210632285.jpg","sets");
	*
	*	Parameters:
	*	$filename: The file name of the image
	*	$folderName: the name of the parent folder of the images. The images will be stored to /webroot/img/$folderName/big/ and  /webroot/img/$folderName/small/
	*/
	function delete_image($filename,$folderName) {
		if(is_file("img/".$folderName."/home/".$filename))
			unlink("img/".$folderName."/home/".$filename);
		if(is_file("img/".$folderName."/big/".$filename))
			unlink("img/".$folderName."/big/".$filename);
		if(is_file("img/".$folderName."/small/".$filename))
			unlink("img/".$folderName."/small/".$filename);
	}
 
    function getFileExtension($str) {
 
        $i = strrpos($str,".");
        if (!$i) { return ""; }
        $l = strlen($str) - $i;
        $ext = substr($str,$i+1,$l);
        return $ext;
    }

	/*
	 * @param $cType - the conversion type: resize (default), resizeCrop (square), crop (from center) 
	 * @param $id - image filename
	 * @param $imgFolder  - the folder where the image is
	 * @param $newName - include extension (if desired)
	 * @param $newWidth - the  max width or crop width
	 * @param $newHeight - the max height or crop height
	 * @param $quality - the quality of the image
	 * @param $bgcolor - this was from a previous option that was removed, but required for backward compatibility
	 */
	function resizeImage($cType = 'resize', $srcfolder, $srcname, $dstfolder, $dstname = false, $newWidth=false, $newHeight=false, $quality = 75)
	{
		$srcimg = $srcfolder.DS.$srcname;
		list($oldWidth, $oldHeight, $type) = getimagesize($srcimg); 
		$ext = $this->image_type_to_extension($type);
		
		//check to make sure that the file is writeable, if so, create destination image (temp image)
		if (is_writeable($dstfolder))
		{
			$dstimg = $dstfolder.DS.$dstname;
		}
		else
		{
			//if not let developer know
			debug("You must allow proper permissions for image processing. And the folder has to be writable.");
			debug("Run \"chmod 777 on '$dstfolder' folder\"");
			exit();
		}
		
		//check to make sure that something is requested, otherwise there is nothing to resize.
		//although, could create option for quality only
		if ($newWidth OR $newHeight)
		{
			/*
			 * check to make sure temp file doesn't exist from a mistake or system hang up.
			 * If so delete.
			 */
			if(file_exists($dstimg))
			{
				unlink($dstimg);
			}
			else
			{
				switch ($cType){
					default:
					case 'resize':
						# Maintains the aspect ration of the image and makes sure that it fits
						# within the maxW(newWidth) and maxH(newHeight) (thus some side will be smaller)
						$widthScale = 2;
						$heightScale = 2;
						
						// Check to see that we are not over resizing, otherwise, set the new scale
						if($newWidth) {
							if($newWidth > $oldWidth) $newWidth = $oldWidth;
							$widthScale = 	$newWidth / $oldWidth;
						}
						if($newHeight) {
							if($newHeight > $oldHeight) $newHeight = $oldHeight;
							$heightScale = $newHeight / $oldHeight;
						}
						//debug("W: $widthScale  H: $heightScale<br>");
						if($widthScale < $heightScale) {
							$maxWidth = $newWidth;
							$maxHeight = false;							
						} elseif ($widthScale > $heightScale ) {
							$maxHeight = $newHeight;
							$maxWidth = false;
						} else {
							$maxHeight = $newHeight;
							$maxWidth = $newWidth;
						}
						
						if($maxWidth > $maxHeight){
							$applyWidth = $maxWidth;
							$applyHeight = ($oldHeight*$applyWidth)/$oldWidth;
						} elseif ($maxHeight > $maxWidth) {
							$applyHeight = $maxHeight;
							$applyWidth = ($applyHeight*$oldWidth)/$oldHeight;
						} else {
							$applyWidth = $maxWidth; 
								$applyHeight = $maxHeight;
						}
						$startX = 0;
						$startY = 0;
						break;
					case 'resizeCrop':
					
						// Check to see that we are not over resizing, otherwise, set the new scale						
						// -- resize to max, then crop to center
						if($newWidth > $oldWidth) $newWidth = $oldWidth;	
							$ratioX = $newWidth / $oldWidth;
						
						if($newHeight > $oldHeight) $newHeight = $oldHeight;
							$ratioY = $newHeight / $oldHeight;									
	
						if ($ratioX < $ratioY) { 
							$startX = round(($oldWidth - ($newWidth / $ratioY))/2);
							$startY = 0;
							$oldWidth = round($newWidth / $ratioY);
							$oldHeight = $oldHeight;
						} else { 
							$startX = 0;
							$startY = round(($oldHeight - ($newHeight / $ratioX))/2);
							$oldWidth = $oldWidth;
							$oldHeight = round($newHeight / $ratioX);
						}
						$applyWidth = $newWidth;
						$applyHeight = $newHeight;
						break;
					case 'crop':
						// -- a straight centered crop
						$startY = ($oldHeight - $newHeight)/2;
						$startX = ($oldWidth - $newWidth)/2;
						$oldHeight = $newHeight;
						$applyHeight = $newHeight;
						$oldWidth = $newWidth; 
						$applyWidth = $newWidth;
						break;
				}
				
				switch($ext)
				{
					case 'gif' :
						$oldImage = imagecreatefromgif($srcimg);
						break;
					case 'png' :
						$oldImage = imagecreatefrompng($srcimg);
						break;
					case 'jpg' :
					case 'jpeg' :
						$oldImage = imagecreatefromjpeg($srcimg);
						break;
					default :
						//image type is not a possible option
						return false;
						break;
				}
				
				//create new image
				$newImage = imagecreatetruecolor($applyWidth, $applyHeight);
								
				//put old image on top of new image
				imagecopyresampled($newImage, $oldImage, 0,0 , $startX, $startY, $applyWidth, $applyHeight, $oldWidth, $oldHeight);
				
					switch($ext)
					{
						case 'gif' :
							imagegif($newImage, $dstimg, $quality);
							break;
						case 'png' :
							imagepng($newImage, $dstimg, $quality);
							break;
						case 'jpg' :
						case 'jpeg' :
							imagejpeg($newImage, $dstimg, $quality);
							break;
						default :
							return false;
							break;
					}
				
				imagedestroy($newImage);
				imagedestroy($oldImage);
								
				return true;
			}

		} else {
			return false;
		}
		

	}

	function image_type_to_extension($imagetype)
	{
	if(empty($imagetype)) return false;
		switch($imagetype)
		{
			case IMAGETYPE_GIF    : return 'gif';
			case IMAGETYPE_JPEG    : return 'jpg';
			case IMAGETYPE_PNG    : return 'png';
			case IMAGETYPE_SWF    : return 'swf';
			case IMAGETYPE_PSD    : return 'psd';
			case IMAGETYPE_BMP    : return 'bmp';
			case IMAGETYPE_TIFF_II : return 'tiff';
			case IMAGETYPE_TIFF_MM : return 'tiff';
			case IMAGETYPE_JPC    : return 'jpc';
			case IMAGETYPE_JP2    : return 'jp2';
			case IMAGETYPE_JPX    : return 'jpf';
			case IMAGETYPE_JB2    : return 'jb2';
			case IMAGETYPE_SWC    : return 'swc';
			case IMAGETYPE_IFF    : return 'aiff';
			case IMAGETYPE_WBMP    : return 'wbmp';
			case IMAGETYPE_XBM    : return 'xbm';
			default                : return false;
		}
	}
	} 
?>

to use it in your controller,


<?php
class FurnitureSetsController extends AppController {

	var $name = 'FurnitureSets';
var $components = array("Image","RequestHandler");

function admin_add() {
 if (!empty($this->data)) { 
  $this->FurnitureSet->create();
   if ($this->FurnitureSet->save($this->data)) {
    // resize the image to 573x380 and create a square thumbnail 80x80
       $image_path = $this->Image->upload_image_and_thumbnail($this->data,"name1", 573,380,80,80, "sets");
    if(isset($image_path)) {
     $this->FurnitureSet->saveField('image_path',$image_path);
    }
    else {
     $this->Session->setFlash(__('The image for the set could not be saved. Please, try again.', true));
    }     

   }

 }
}

Note that you can modify the resize settings in the upload_image_and_thumbnail method.

The view..

<div class="furnitureSets form">
    <?php echo $form->create('FurnitureSet',array('type' => 'file'));?>
    <fieldset>
        <legend>
            <?php __('Add Furniture set');?>
        </legend>
        <?php
		echo $form->input('name');
		echo $form->input('country_id');
			?>
		<div class="input">
		<label for="Image/name1">Image</label>
		<?php
		echo $form->file('Image/name1', array('size' => '40'));
		?>
		</div>
		<?php
		echo $form->input('is_featured');
		echo $form->input('furniture_material_id');
		echo $form->input('furniture_category_id');
		echo $form->input('is_indoor');
		echo $form->input('is_outdoor');		
		echo $form->input('CustomerType');
	?>
    </fieldset>
    <?php echo $form->end('Submit');?>
</div>

Now as promised, the code!
30/4/2009: after modification from comments
17/7/2008: Old version

Again, thanks Wendy for your code!

Advertisements

74 Responses to "Enhanced: Image Upload Component for CakePHP 1.2"

Hi Ahmed, thanks for the nice and simple component. It works like a charm for me.

This works great! What a superbly easy component to use. The only thing that tripped me up was that my PHP config didn’t have the GD2 library running, but a quick tweak in the php.ini and all was well.

Good stuff! Should definitely consider putting this up on the Bakery or similar.

This works well, thanks! But what if I want to redirect after uploading an image? I get an “Headers already sent error message”, any ideas? thanks in advance.

Never mind, I had some whitespace after the image.php script, fixed now.

@sabbour:

Do you have the view for the FurnitureSetsController?

I updated the post to include the view

hi! error upload image png. fix: Insert on function resizeImage():
if( version_compare( phpversion(), “5.1.0”, “>=” ) ) {
$quality = 9;
}

I’ve been trying to get this compontent working for awhile now and I can’t seem to get it right. I am receiving back an image path and am not recieving any errors. I have chmod 777 my big small and home dir, but I still cannot get a single image to save even though I am receiving the image name. I have also tried to find the error and it seems like the if (is_uploaded_file($data[‘Image’][$datakey][‘tmp_name’]))

statement isn’t even firing properly. Any ideas?

nice work BUT

why dont you choose simple name for controllers /table/model ….. so that your code can be digested with out much efforts…

thanks

Excellent component…

just wanted to know if I want to do this using AJAX. I want to AVOID jquery for some reason. I tried SWF but cant get it working.

Any Ideas

once again thanks

ummm, is it just me or is that view/controller code all wrong.

First of all the form code renders as:

Should that name not be [Photo][Image][name1]?

(my model is called “Photo” not “FurnitureSet”)

and the part where you instantiate the Image: “upload_image_and_thumbnail($this->data,”name1″…

The component fails because you should be passing $this->data[“Photo”], no?

I’m getting: Undefined index: Image.

Thanks

Opps your site strips tags… the form code above should be …
name=”data[Photo][Image/name1]”

should that not render as
name=”data[Photo][Image][name1]”?

Hey again,
Ya, it looks like in the latest version of Cake, 1.2.0.7692 RC3, you need to use the ‘dot’ notation in your view.

so,
echo $form->file(‘Image/name1’, array(‘size’ => ’40’));
becomes
echo $form->file(‘Image.name1’, array(‘size’ => ’40’));

and you do have to pass the image class:
$this->data[“Photo”] (in my case Photo)
instead of:
$this->data

actually you can just pass: $this->data,
but you do have to use dot notation now.

sorry

Hey sabbour,

NICE WORK 🙂 Works flawlessly!

Here’s a note to whoever’s getting an “error” whereby you can’t see the file getting uploaded – I spent quite a while “debugging” the script wondering if it was the script’s error, but it turns out its a bug/config thing in XAMPP for Mac.

The default installation of XAMPP for Mac (is horribly crippled, compared to its Windows counterpart) – and hence you MUST manually set the upload_dir inside the php.ini file!

This is because PHP defaults to /tmp in Mac, but /tmp is not writable to all (i.e, NOT chmodded 777).

Hence, set the dir to upload to inside php.ini and all works flawlessly 🙂

PS: Strangely, “usual” PHP uploading works fine.. Maybe its a thing with cake, i don’t know 😛

Regards,
Kelvin

Very nice!

But, pay attention in the block line 92..118
if (is_uploaded_file(..){

}

the return $filename must be INSIDE this block or a file that IS NOT UPLOADED give a true result.

-> put the “}” in line 118 below the return $filename

Hello, I’m using your component, thanks!
But, I think the image processing isn’t doing very all, I don’t know if it is a problem into your script. Some images simply are saved as invalid images, and I can’t see/open them.
Do your know what can that be?

Thanks!!!!!!!

thank you, greetings from Chile!

Wow! This component is very good! I have modified the code to create the folder that contains folders home, big and small.

$tempuploaddir = “img/temp”; // the /temp/ directory, should delete the image after we upload (no modified)
$rootuploaddir = “img/”.$folderName; // the root controller directory (added)
$homeuploaddir = “img/”.$folderName.”/home”; // the /home/ directory (no modified)
$biguploaddir = “img/”.$folderName.”/big”; // the /big/ directory (no modified)
$smalluploaddir = “img/”.$folderName.”/small”; // the /small/ directory for thumbnails (no modified)

// Make sure the required directories exist, and create them if necessary
if(!is_dir($rootuploaddir)) mkdir($rootuploaddir, 0777); // (added)
if(!is_dir($tempuploaddir)) mkdir($tempuploaddir, 0777); // (modified)
if(!is_dir($homeuploaddir)) mkdir($homeuploaddir, 0777); // (modified)
if(!is_dir($biguploaddir)) mkdir($biguploaddir, 0777); // (modified)
if(!is_dir($smalluploaddir)) mkdir($smalluploaddir, 0777); // (modified)

Thanks for the code, has been helpful.

hi!

first of all thank you for this component, it’s great! but now my problem: I’m using XAMPP for Windows and on my localhost it works just fine. When I upload it to the server I get the error Error Uploading File!. Why is it? I set my \app\temp directory writable (777) but it still doesn’t work? can anyone help me? thanks 🙂

ok, got it! I set the wrong temp directory writable. SORRY! It’s late and was watching soccer on tv along the way. but still, GREAT component!!

@rodin and @fabio:
Yes, I found this bug but it is not solved by putting the return statement inside the if statement.

The exit() statement should be taking care of this, but the $filename variable is actually set before we leave this function, so we have to change the statement to

if (!copy($data['Image'][$datakey]['tmp_name'],"$tempfile"))
                        {
print "Error Uploading File!.";
							unset($filename);
                            exit(); 
                        }

I’m trying it on a new project now. I will update the code too to reflect this change.

thank you, greetings from Brazil!

nice work dear..thanks 😀

Excellent work!
A little tweaking to get it to do what i wanted, but works great.
Thanks alot!

Thanks a lot for this useful component!

Thank you very much for publishing that code i saved lot of my time. Greetings from Poland!

This is how I set mine up… WWW_ROOT and DS are global constants in cake; which are useful.

also the mkdir variables weren’t in the right place; so didn’t actually work recusively

class {

var $original_folder = "original";
var $thumb_folder = "thumb";

function upload(...) {
...
$tempuploaddir = WWW_ROOT."img".DS."temp"; // the /temp/ directory, should delete the image after we upload
$biguploaddir = WWW_ROOT."img".DS.$folderName.DS.$this->original_folder; // the /big/ directory
$smalluploaddir = WWW_ROOT."img".DS.$folderName.DS.$this->thumb_folder; // the /small/ directory for thumbnails

if(!is_dir($tempuploaddir)) mkdir($tempuploaddir,"0777",true);
if(!is_dir($biguploaddir)) mkdir($biguploaddir,"0777",true);
if(!is_dir($smalluploaddir)) mkdir($smalluploaddir,"0777",true);
...
}

...

}

@Chickenhen
Nice catch 🙂 I think I modified it in my working folder but I didn’t put it online.

Maybe I should put it on Google code..! 🙂

Is it possible to resize the images to 72dpi?

Can anyone tel me what is Image in Image/name1 if name1 i is database table field ???
I can’t get this right!!!

@Drum: No, Image/name1 has nothing to do with the database.

If you create an input in the view as such:

<?= $form->file('Gift.photo') ?>

this simply means that you can access it through the $this->data array in the controller as:

$this->data['Gift']['photo'];


but please note that in the Gift model, there is actually no “photo” column, it is called “image_path”.
You have to take care because if you name the input after the column in your model where you store the path of the image, CakePHP will try to save the image data inside the database, which will obviously fail!

All this component does is that it handles uploading and resizing the image, while giving you back the resulting image name. You are free to use that image name and store it from the controller.

It is a bit klunky, but here is another look at the controller save method:

function add() {		
		$uploaded = false; // to handle logic for displaying the success or failure
		$saved = false; // to handle logic for displaying the success or failure
		$needupload = false; // will be true if we actually want to upload something

		if (!empty($this->data)) {
			$this->Gift->create();
			
			if ($this->Gift->save($this->data)) {
				$saved = true;		
				
				if(!empty($this->data['Gift']['photo']['name'])) {
					$needupload = true;
					$image_path = $this->Image->upload_image_and_thumbnail($this->data['Gift']['photo'],600,450,174,117, "gifts");
					
					if(isset($image_path)) {
						$this->Gift->saveField('image',$image_path);
						$uploaded = true;
					}				
				}
			}
			
			if($saved && ($uploaded || !$needupload)) {				
				$this->Session->setFlash(__('Gift saved!', true),'flash_success');
				$this->redirect(array('action'=>'index'));
			}
			else if($saved && !$uploaded && $needupload) {
				// Gift was saved but we needed to upload and the saving failed
				// We have to rollback this, so we have to delete the gift that we just added
				$this->Session->setFlash(__('The image for the gift could not be saved. Please, try again.', true),'flash_error');
				$this->Gift->del($this->Gift->id);
			}
			else {
				$this->Session->setFlash(__('The gift could not be saved. Please, try again.', true),'flash_error');
			}
		}
	}

The view:

<?= $form->create('Gift',array('type' => 'file')); ?>
		<div>
			<label>Title<span>Gift title</span></label>
			<?= $form->input('title',array(
				'error'=>array(
					'required' => 'You have to fill in the gift title.'
				),
				'class'=>'textbox',
				'label'=>false
			));?>
		</div>
		<div>
			<label>Description<span>Gift description</span></label>
			<?= $form->input('description', array( 'label' => false,'class' => 'textarea','type'=>'textarea' )); ?>
		</div>
		<div>
		<label>Image<span>Gift photo</span></label>	
			<?=  $form->input('photo', array('type' => 'file','label' => false)); ?>
		</div>
<?= $form->end('Save');?>

I’m not sure if that was clear..I really need to refactor the way the component works, and maybe wrap this inside a real transaction instead!

Thank you for your answer!
I’m trying to develop a user friendly web site and i have tried all image upload scripts for cakephp published on web, and i write some myself but I’m not happy whit anyone of those. So far. My goal is to save a image_path into a database field named image_path(or so). If a user wants to delete or change it, the option is here for him(or her)…

Hi,

improvment of ninhhungs png fix (https://sabbour.wordpress.com/2008/07/18/enhanced-image-upload-component-for-cakephp-12/#comment-97):

imagepng($newImage, $dstimg, 9 – ($quality / 100.0) * 9);

this maps the quality paramter to the 0-9 range of imagepng’s quality setting (0 best, 9 worst).

I have used this successfully for multiple file uploads, but the filename generation has to be modified slightly. The reason is that if you try to upload multiple files at the same time (with the same form) it will generate the same name for (many) of them since it’s using the timestamp

In image.php, find the lines
$id_unic = str_replace(“.”, “”, strtotime (“now”));
to this you can add an extension depending on your image_path, for instance I’ve added (since my datakeys are named filedata_file1, filedata_file2, etc)

#to prevent naming conflicts when uploading multiple files simulaneously,
#changed to append last 3 chars of datakey to filename
$index_of = stripos($datakey, “_”);
$filename = $id_unic . substr($datakey, $index_of, strlen($datakey)-$index_of);

@Victor:

Actually, I changed it in my other projects to use UUIDs generated by CakePHP:

$id_unic = $uuid = String::uuid();
$filename = $id_unic;

And the code posted is already updated 😉

May I upload it to github.com under the MIT license, so as to have it easily mantained on a public repostory?
Thanks in advance;
Tute.

Yes, I always wanted to do that 🙂

Can you please put a reference to my blog somewhere? And also please after putting it on github, give us the link so that I can update the post.

Thanks!

Excellent, thank you!

It’s version controlled, with appropriate references, in:
http://github.com/tute/Thumbnail-component-for-CakePHP/

See you here and there!

If i store the path in database, resize is inposible?

I am suddenly having a problem displaying png files, even though I’m doing exactly the same as for other types (jpegs displays well for example). All the paths are the same.

Any ideas why pngs don’t display?

Hello, thnx for this component. I am newbie in cakephp and trying to use it (the github version). The problem is that no file is uploaded in the “files” directory, however that directory is created, and thumbnails are nicely uploaded. Also the file name is being saved in database. Can you please help me? I am using xampp, windows xp, cakephp version 1.2.x.x_02.08.2009.

OK, I have make things done. Though now facing the problem of uploading large files (>10MB) caused by gd. May be I have to spend more time with it. Thanks anyway.

@Victor, the PNG problem was that it’s quality range is [0..9], not [0..100]. Changing line 281 solves the problem:

– imagepng($newImage, $dstimg, $quality);
+ imagepng($newImage, $dstimg, round($quality/10));

Great component, using it-. 😀

You must update y’r comments for resizeImage function in file:
/*
* @param $cType – the conversion type: resize (default), resizeCrop (square), crop (from center)
* @param $id – image filename
* @param $imgFolder – the folder where the image is
* @param $newName – include extension (if desired)
* @param $newWidth – the max width or crop width
* @param $newHeight – the max height or crop height
* @param $quality – the quality of the image
* @param $bgcolor – this was from a previous option that was removed, but required for backward compatibility
*/
function resizeImage($cType = ‘resize’, $srcfolder, $srcname, $dstfolder, $dstname = false, $newWidth=false, $newHeight=false, $quality = 75) {

Muchas Gracias!!!! Thanks So much!!!! Saludos desde Colombia!!!!

Using this in a ‘gallery_controller’, how would i use this to edit the gallery details, and upload multiple images in to an image mysql table related to that gallery???

Nice job! There is a small typo in your view as already said in the comments:
echo $form->file(‘Image/name1’, array(‘size’ => ’40’));
should be:
echo $form->file(‘Image.name1’, array(‘size’ => ’40’));

Hello

Kind of new to cakePhp … tryin to use thia component but i keep getting

Undefined index: name [APP\controllers\components\image.php, line 45]

Any idea … ?

Thanks

another thing is buggin me …

the signature for upload_image_and_thumbnail is

($data, $maxw, $maxh, $thumbscalew, $thumbscaleh, $folderName)

so why do u call

$this->Image->upload_image_and_thumbnail($this->data,”name1″, 573,380,80,80, “sets”

Am i missin something … ?

cheers

hello

got it all figured out, parts of thge problems i was experiencing had been pointed out in rpevious comments

As i was sayin, in the code reported at the beginning of the post there seems to be a mismatch between the signature of upload_image_and_thumbnail and its call in the controller.

To summarize the changes that did it for me, in case anyone was havin my same problems:

___

In

($this->data,”name1″, 573,380,80,80, “sets”)

“name1” should be removed and $this->data replaced with $this->data[“Image”][“name1”]

And in the view

echo $form->file(‘Image/name1’, array(‘size’ => ’40’));

should be

echo $form->file(‘Image.name1’, array(‘size’ => ’40’));

Please feedback if this is wrong ..

cheers

@dani: Hello!
Please note that the most updated version with all of those problems fixed is now on GitHub as mentioned in the first post
http://github.com/tute/Thumbnail-component-for-CakePHP/

sabbour … next will read the intro before the code 😉

and thanks, it’s a great component …

cheers

Is there a working example of this code. I am trying to use the updated version found on Github but can’t seem to get it to work.

Basically I am trying to upload an image (as part of the users profile) when I add a new user. The form is being successfully submitted but my image column does not get populated and the image does not get added to the /webroot/attachments/photos/ directory.

There seems to be a disconnect between the Github implementation and the notes here. Which one should we be using? It’s very confusing to get two different sets on instructions.

Thanks in advance.

Please use the GitHub version 🙂

I figured out in the github version that you don’t have to specify both width and height if you scale the image.

‘big’ => array(null, 500, false),
‘med’ => array(164, null , false),
‘small’ => array(null , 23, false)

Like this

I’ve improved it’s API: now it’s not necessary anymore to manually save the path, content_type or file size, since it updates it automatically given some columns in DB with special names.

Configuration options for those column names (now works following conventions only) are about to come!

I remember the repository URL: http://github.com/tute/Thumbnail-component-for-CakePHP

Thank you all! 🙂

It’s upload the image from the server, but never save the image name on database. Someone have any clue to save the new image name on database?

Am I being really thick or can this component not be set to save uploaded files with the same filename that they have on the host computer? Whenever I upload a file using this component it always gives the file a very long and very random filename (such as 4d4bff4a-530c-4016-b0ef-52fec1258ed3.pdf). The file is saved as postal_receipt_vga-cable.pdf on my computer.

Indeed the component does that. Should be a configuration option, or it could check if a file with the original filename exists, and rename it if it does.

Line to blame:
https://github.com/tute/Thumbnail-component-for-CakePHP/blob/master/attachment.php#L93

Kind regards.

Undefined index: name [APP\controllers\components\image.php, line 89]
i am getting this error message could any one please help i stucked here from 4 days …. please anyone help…..?

@TuteC or Sabbour
Thanks for the updated version on Git.
Running into something I hope is simple.
I have the the component successfully uploading the renamed file to the server, but no records are inserted in my Model.
Wondering if I just have something simple misaligned in my controller:

function upload() {
if (!empty($this->data)) {
$this->Pet->create();
if ($this->Pet->save($this->data)) {
$this->data = $this->Attachment->upload($this->data[‘Pet’]);
$this->Session->setFlash(__(‘The Pet has been saved’, true));
$this->redirect(array(‘action’=>’index’));
} else {
$this->Session->setFlash(__(‘The Pet could not be saved. Please, try again.’, true));
}
}
}

And the view:

create(‘Pet’, array(‘type’ => ‘file’));
echo $form->input(‘pet’ , array(‘type’ => ‘file’));
echo $form->end(‘Save my pooch’);
?>

Hi Eric,

$this->Attachment->upload() should be called before $this->Pet->save().

Regards,

Tute.

hi
my code is :
” $this->Attachment->thumbnail($this->data[‘Pet’] , ‘aaa’ , 640, 480, false); ”

but i have alot of errors :

getimagesize() [function.getimagesize]: Filename cannot be empty [APP\controllers\components\attachment.php, line 188]

Warning (2): unlink(D:\wamp\www\cakephp\app\webroot\attachments\pets\avatar\aaa\) [function.unlink]: Permission denied [APP\controllers\components\attachment.php, line 205]

and then :

Warning (2): split() expects parameter 2 to be string, array given [APP\controllers\components\attachment.php, line 148]

Warning (2): end() expects parameter 1 to be array, null given [APP\controllers\components\attachment.php, line 148]

Can you help me ?
thanks

I needed to alter the default behavior for one particular type of image, so I over wrote the image size array with the following:

$this->Attachment->config[‘images_size’] = array(‘banner’ => array(945, 535, ‘crop’));
$this->Attachment->upload(…);

kindky upload the code again

This works great!

Hi,

Sorry to bother you with my question, but this is bugging my mind…

Is there any way to use your thumbnail component from other mode than the calling model? For example in the example application PET –model is using the component and the data is saved to that model.

I have a situation, where my model that uses component is called IMAGE and I would like to save images from COLLABORATION –model. This is because when I save collaboration messages, I would like to save image (and it’s different versions) as well in the same controller. I seem not to find the right format of the code to save data, Cake always says “Undefined index: collaboration” when I call it this way:

$this->Attachment->upload($this->request->data[‘Collaboration’]);

Also calling this way won’t work (naturally):

$this->Attachment->upload($this->request->data[‘Image’]);

Is there any discussions around this or blog that I could ask these questions from community?

Thanks,

// Jari

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Ahmed Sabbour's Facebook profile
July 2008
S M T W T F S
« May   Oct »
 12345
6789101112
13141516171819
20212223242526
2728293031  

Tweets

RSS StackOverflow

Recently bookmarked

%d bloggers like this: