Image Upload Component (CakePHP)
Thanks to some fine work by Ben Borowski, uploading images in CakePHP is easy as kicking your kids. I’ve used this component for quite a few projects. It’s safe to say that it rules.
Learn how to use it, love it, code it.
There have been updates to this article. Please make sure you note any changes before commenting.
This article covers uploading one image at a time. To learn how to upload multiple images at once, see the Multiple Image Uploads Into Single MySQL Table (CakePHP) article.
Dropping The Knowledge (pretext)
Using the upload component is super simple and allows for optional input to customize the resulting image.
/*
* upload
* - handle uploads of any type
* @ file - a file (file to upload) $_FILES[FILE_NAME]
* @ path - string (where to upload to)
* @ name [optional] - override the default file name
* @ rules [optional] - how to handle file types
* - rules['type'] = string ('resize','resizemin','resizecrop','crop')
* - rules['size'] = array (x, y) or single number
* - rules['output'] = string ('gif','png','jpg')
* - rules['quality'] = integer (quality of output image)
* @ allowed [optional] - allowed filetypes array
* - default: array ('jpg','jpeg','gif','png')
* ex:
* $result = $this->Upload->upload($file, 'uploads', null, array('type' => 'resizecrop', 'size' => array('400', '300'), 'output' => 'jpg'));
*
*/
Each value should be self explanatory. If you need further explanation, post a comment and we’ll go through it together.
1. Download Upload Component & Create Upload Dir
Download the following zip file, extract it, and place upload.php in your /app/controllers/components/ directory.
Download the complete image upload component here.
Now create an ‘uploads’ directory in /app/webroot/img/uploads/ and make sure to give the directory 777 (writable by all) permissions.
2. Prepare Your Controller
Next we’ll slap the necessary code in place to handle a single image upload. (To upload multiple images at once, check out this article.)
class ImagesController extends AppController {
var $name = 'Images';
var $helpers = array('Html', 'Form');
var $components = array('Upload');
function upload() {
if (empty($this->data)) {
$this->render();
} else {
$this->cleanUpFields();
// set the upload destination folder
$destination = realpath('../../app/webroot/img/uploads/') . '/';
// grab the file
$file = $this->data['Image']['filedata'];
// upload the image using the upload component
$result = $this->Upload->upload($file, $destination, null, array('type' => 'resizecrop', 'size' => array('400', '300'), 'output' => 'jpg'));
if (!$result){
$this->data['Image']['filedata'] = $this->Upload->result;
} else {
// display error
$errors = $this->Upload->errors;
// piece together errors
if(is_array($errors)){ $errors = implode("<br />",$errors); }
$this->Session->setFlash($errors);
$this->redirect('/images/upload');
exit();
}
if ($this->Image->save($this->data)) {
$this->Session->setFlash('Image has been added.');
$this->redirect('/images/index');
} else {
$this->Session->setFlash('Please correct errors below.');
unlink($destination.$this->Upload->result);
}
}
}
* Highlighted code represents things relating to the upload class. The rest is default Cake code.
3. Create Your View
In the appropriate view controller (in this case, /app/views/images/upload.thtml), use the following code to insert a file upload field:
<?php echo $form->labelTag('Image/images', 'Image:' );?>
<?php echo $html->file('Image/filedata');?>
This will create the following HTML:
<label for="Image">Image:</label>
<input type="file" name="data[Image][filedata]" id="ImageFiledata" />
Complete The Package
To make things easy, I’ve included all the above files in a single download. Get the complete CakePHP image upload package here.
If you have issues, comment. I’m happy to help.
Updates
Nov 8th, 2007: The uploads component (upload.php) has been modified to correctly handle filetypes.
Nov 6th, 2007: Errors are now gracefully displayed. An allowed variable has been added to the upload component regarding allowed filetypes. A .sql file has been included for easy setup of the images MySQL table.
Jan 16th, 2008: Thanks to Ruben, a small Jeff correctly pointed out that Ruben’s “fix” was actually an unneeded glitch. The component has been reverted to working form.$fileType glitch was discovered… and fixed. Thanks Ruben!

Comments(37)
Izzz nice, I like it!
PHP Peice of CAKE!
[...] Image Upload Component (CakePHP) [...]
Thanks dude. The upload component download and package download links have been fixed. Download away!
Howdy! Thanks for posting this code, it looks like it’ll be perfect for what I want to do. That said, I can’t get it to work, so I hope you can help me resolve a problem.
I have downloaded the package you provided and placed each of the files in the correct place, but received a couple of errors:
1. Missing Component Class
When I hit
/images/upload/I receive a notice stating “the component class UploadComponent you have set in ImagesController can’t be found or doesn’t exist.” It also tells me to addto
app/controllers/components/upload.php. When I add it the error disappears and I am presented with the proper view.2. After following the steps in point 1, I can access the form, but when I submit the form I receive the error “Call to undefined function: upload() in [Path to Cake]/app/controllers/images_controller.php on line 22″ It seemed odd that I should have an empty UploadComponent as in point 1, so I changed the class name in upload.php from upload to UploadComponent which eliminated this error. I’m not sure if this is correct though. Should I have done something else?
3. With the name change noted in step 2, I have eliminated the previous error, but now receive “Undefined index: quality” in upload.php on line 86. This was pretty easy to resolve, though I think you may need to modify your example above, which is missing the quality option for the results in the upload function in
images_controller.php. I modified line 22 to fix the problem:So, the form now submits, and doesn’t throw any errors, but the file is not added to
/app/webroot/img/uploads/nor is a confirmation message shown in the flash. I verified that/uploads/is set to777. I’m running GD (2.0.28 compatible)Any help is greatly appreciated!
Alex, the UploadComponent I included in the zip file was old and not written to be compatible with CakePHP. (Lame of me.)
The zipped package has been fixed. Sorry for the mix up.
Hi Koa, thanks for the speedy reply! I pulled down a fresh copy of the zipped package but in comparing the files I don’t see any differences. The issues I noted above are still present in the files. The timestamps on the files within the zip match between what I hd downloaded earlier today and the one I just pulled down.
Oh, and I remembered one other error the final closing curly brace is missing from images_controller.php
Cheers!
All better.
Thanks again Alex. At least one of us has eyes.
Hi, great component. This is just what I needed. I was wondering if there is a way to specify a destination filename. I would like to prepend the user_id so people don’t overwrite each others files. Thanks again for the nice work.
This is really great. Thanks for the help.
One question though: did you post the multiple upload component yet?
I can really use it!
Ronnie, the component automatically creates a unique filename by adding a unique number at the end of the filename.
The function which handles this task is called
uniquename, line 301 of theupload.phpcomponent.[...] article assumes you use the CakePHP image upload component I covered a while back. If you’re not using it, you should [...]
Thanks Koa, the new zip addresses those problems, though for some reason the file isn’t saved to disk. Well, rather it is, but then immediately deleted due to the last bit of code in the controller:
if ($this->Image->save($this->data)) {
$this->Session->setFlash('Image has been added.');
$this->redirect('/images/index');
} else {
$this->Session->setFlash('Please correct errors below.');
unlink($destination.$this->Upload->result);
}
I’ve tracked the problem down to that one check, and if I comment out the unlink line all works as expected – the image is saved to the file system. I’m of a mind to eliminate that check and just save the file, but I thought I’d ask you before I do..?
Also, the flash message never appeared, so it was a bit of fun trying to track down the root of the issue. is $this->Session->setFlash a 1.2.x way of doing things? If so, then I won’t worry about it for now as I am using 1.1.x. Otherwise, why would I use it instead of $this->flash? Trying to track down information about it hasn’t provided much useful info.
Thanks again!
Alex, I fixed the
images_controller.phpfile to correctly save the data to theimagesMySQL table. You might have noticed that although the image saved when you uncommented theunlinkcode, the image name was not saved to MySQL.Secondly,
$this->Session->setFlashis valid Cake 1.1.x code, but like most Cake variables, it’s not well documented. To use it, use the following in your/app/views/layouts/default.thtml:Now instead of displaying messages on a seperate page, the message will appear on whatever page specified using
$this->redirect().Hope this helps!
Very cool, thanks!
FYI, the pasted code includes curly single quotes which cause errors in PHP, but using a standard single quote fixes that problem.
I’m goign to pull down the updated file, and once I have it working I’ll take a look at the multi-image version that you posted about recently.
Cheers!
When we upload the images its show “Warning: imagejpeg(): Unable to open ‘\/dracena0.jpg’ for writing in c:\apache2triad\htdocs\loco\app\controllers\components\upload.php on line 284 Warning: Cannot modify header information – headers already sent by (output started at c:\apache2triad\htdocs\loco\app\controllers\components\upload.php:284) in C:\apache2triad\htdocs\loco\cake\libs\controller\controller.php on line 447”
Can you help me for upload images
jeet, you need to make sure to give write permissions to the
uploadsfolder – 777 should do it.don’t forget to put enctype=”multipart/form-data” into the form tag or the file name is the only thing returned.
I used to use Cake, although I came to the conclusion I despised it after a while. Not because it can code ideas faster than I can think of them, but on a superficial note I didn’t like the names it gave to HTML form elements so it could automate the saving and loading, but I also didn’t like the fact that it’s a VERY tightly coupled framework with low cohesion.
We were discussing this over at TalkPHP.com the other week and came to the conclusion that one of the best frameworks for its high cohesion and loose coupling was in fact Zend Framework, and if I may say so myself, Zend Framework is definitely the one for me!
I’m having the same issue as jeet and I have given 777 permission to the img/uploads folder. Any suggestions?
Perkster, I hate to sound like a broken record, but it must be a permission issue.
Based on a quick Google search, I’m guessing that like jeet, you’re on a Windows machine. It seems like some Windows users have permission issues when trying to use PHP’s
imagejpeg()function.I’ll try playing around with this in XP and post what I find.
Great stuff! Problem though, not with this component, how do I use it? I guess it’s me of a general how do you use components question. I’ve gone through the component section in the manual and I don’t get it (sorry I’m slow and a bit impatient tonight).
I am using it with a Product controller, that has the add, edit…etc methods. I want the fileupload on my product forms. How can I achieve this? Any help will be greatly appreciated!!!
Duh!, never mind I’m all sorted. Thanks :)
Hi!
Got the same prob than jeet
(Permission denied [CORE/app/controllers/components/upload.php, line 284])
Although I did ‘chmod 777 uploads’
Any ideas?
I’m getting the following response and I have no clue why. I’m on a Mac and I’ve set folders to 777.
Please help—
Warning: imagejpeg() [function.imagejpeg]: Unable to open ‘//20.jpg’ for writing: Permission denied in /Users/dan/Sites/archive/app/controllers/components/upload.php on line 284
Warning: unlink(/) [function.unlink]: Is a directory in /Users/dan/Sites/archive/app/controllers/images_controller.php on line 163
hi koa,
im having the same issues as jeet a few others. you’ve said you will be having a look at this script on xp, any luck so far?
thanks
malik, Dan, Clonix, etc:
I hear your cries for help, but I cannot replicate the error, even on Windows XP. After looking at your errors above, I think your
$destinationvariable is not being properly set.In your
images_controller.php, try addingexit($destination);right after setting the$destinationvariable. That should echo the destination path when you try uploading an image. View it and make sure it’s correctly pointing to your uploads directory.I’ve tested this script on 11 different local machines and 8 servers with no problems. Hopefully each one of you will figure out what the hell is going on.
Godspeed.
hi koa
i solved the problem i was having.
heres the solution for the others who were having the same issue:
inside the components/upload.php it requires the gd library. in windows some php installations dont have gd lib enabled in php.ini
—————————————
The
php_gd2.dllis included in a standard PHP installation for Windows, it’s not enabled by default. You have to turn it on, the user may simply uncomment the lineextension=php_gd2.dllinphp.iniand restart the PHP extension.Change:
#extension=php_gd2.dllTo:
extension=php_gd2.dllYou may also have to correct the extension directory setting from:
extension_dir = "./"Or:
extension_dir = "./extensions"NOTE: SUBSTITUTE THE ACTUAL PHP INSTALLATION DIRECTORY ON *YOUR* COMPUTER.
To (FOR WINDOWS):
extension_dir = "c:/php/extensions"Thanks to Benoit Blais for this last point. Thanks also to Alan MacDougall and Perculator.
—————
for more information
http://www.libgd.org/FAQ_PHP#How_do_I_get_gd_to_work_with_PHP.3F
hope this is helpful
thanks for the componet koa
Hey guys.. i get the following error:
Parse error: syntax error, unexpected ‘;’, expecting T_FUNCTION in /usr/www/virtual/ljmenace/www.whitepridenation.com/app/models/image.php on line 47
so its PROBABBBLYY my eyes playing tricks on me.. where am i forgetting to close something or ???
Thanksss!
PS GREAT HELP component by the way.
ya weird i actually get the same message!
Parse error: syntax error, unexpected ‘;’, expecting T_FUNCTION in /usr/www/virtual/user/www.example.com/app/models/image.php on line 47
malik, great work! Thank you for posting your solution.
Undefined index: Image [CORE\app\controllers\images_controller.php, line 19]when i m uploading any photo i get this error and photo is not saving in my mysql table.
plz help me.
Thanks
Great work! I just had to change
if(!in_array($this->ext($fileName),$this->_allowed)){into
if(!in_array($this->ext($fileType),$this->_allowed)){Ok, figured out some things that I think someone may need to look at.
I traced my problem to the upload.php component file. Specifically to the ext() function that determines what a image’s file extension is. apparently it is being fed the fileType not the fileName, the ext() function is looking for the fileName to determine the the extension.
Now based on the comment by Ruben, that was changed from that for some reason.
To give further info – this is running on an Apache 2.2 server being uploaded from FireFox.
Hope this helps
Jeff, please have a look at the updates above – I believe this problem has been fixed.
If you look at Ruben’s post it creates the problem.
Where he takes
if(!in_array($this->ext($fileName),$this->_allowed)){
into
if(!in_array($this->ext($fileType),$this->_allowed)){
it should be that only reversed so that you change it from $fileType to $fileName
Jeff, good call. Things have been changed back.
This upload component has been used with over 15 projects without a problem. I’m going to assume whatever kinks existed upon release have pretty much been smoothed over.
A big thanks goes out to everyone who contributed to building this killer component!
[...] Image upload Component [...]