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("",$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:
Image:

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 $fileType glitch was discovered… and fixed. Thanks Ruben! Jeff correctly pointed out that Ruben’s “fix” was actually an unneeded glitch. The component has been reverted to working form.