FileUploadPlugin v5.0 released!
Date: Fri, Apr 16th 2010, 22:52 Author: nick Views: 1613 Comments: 25 share
Please Support:
CakePHP File Upload Plugin
Info:
- Version: 6.1.1
- Requirements: CakePHP 1.x, PHP
- Docs: CakePHP File Upload Plugin API
- Article: CakePHP File Upload Plugin Discussion and Examples
Get it:
Download Now
- svn co http://svn.github.com/webtechnick/CakePHP-FileUpload-Plugin file_upload
I'm excited to announce the newest v5.0 release of the popular File Upload Plugin. There have been a lot of new features since the last major release and I'll discuss each one in depth.
At a glance:
- Validation, and file upload errors now display back to the view
- new 'required' key setting
- new 'maxFileSize' key setting
- new 'unique' key setting
- new 'fileNameFunction' key setting.
Any errors that occur during a file upload will now be presented back to user just like any other standard model validation error. If more than one error occurs, each subsequent error will be added to the model's validation errors. This means no more guess work for the developer or user over what went wrong during the upload (ie file was too large, file type not allowed, etc...).
This is a behavior specific new feature. By setting the key 'required' to true you will require an upload to be made if the Model key is present in the saveAll function. This setting is false by default.
Now anywhere in your app if you attempt to preform a $this->saveAll($data, array('validate' => 'first')); with the file model set as an associative key, an uploaded file will be required as well. If no file is detected during that saveAll the entire save is exited and a validation error occurs.
maxFileSize is a new key setting that allows a developer to limit the size of an upload (note: this does *not* overwrite the limit set in php.ini). This is useful, to tone down the size of uploaded files allowed. The setting takes an int and corresponds to the byte size allowed. If set to false, no file size restrictions (other than those set in php.ini) are enforced on the uploaded file. maxFileSize is false by default.
Example:
Until now, the File Upload Plugin made sure never to overwrite any previously uploaded file. That is still the default behavior, but now you can turn that feature off if you wish.
When unique is set to false, uploaded files will overwrite files on the server with the same name. This setting is true by default.
We saved the best for last. A much requested feature was the ability to manipulate the resulting filename in a number of ways. Until now, the only way a user could manipulate the file was in a beforeSave(), but that still required the developer to manually rename the file on the server. Some suggested using a sha1 hash, others a md5 hash, and the rest wanted the ability to define their own function to handle the resulting filename. I've decided to make you all happy!
Enter fileNameFunction setting. With this setting you can define your own filename filtering function, or use any built in PHP hashing function.
Examples:
Defining fileNameFunction as sha1, the resulting filename will first be passed into sha1() and then moved to the server and saved to the database. You can use *ANY* PHP function you wish, including functions you define either in bootstrap.php or within your Model.
Bootstrap.php Example:
You can also define it within the same Model:
NOTE: The function you choose must return a string. If the resulting hash function does *not* return a string, the save will be halted and a validation error will occur.
I hope you enjoy the new features. As always, comments are appreciated. If you enjoy the plugin and wish to help keep it supported, please consider a donation (or click an ad a few times. :) ).
Enjoy,
Nick
New Features
At a glance:
- Validation, and file upload errors now display back to the view
- new 'required' key setting
- new 'maxFileSize' key setting
- new 'unique' key setting
- new 'fileNameFunction' key setting.
Validation errors
Any errors that occur during a file upload will now be presented back to user just like any other standard model validation error. If more than one error occurs, each subsequent error will be added to the model's validation errors. This means no more guess work for the developer or user over what went wrong during the upload (ie file was too large, file type not allowed, etc...).
Required setting
This is a behavior specific new feature. By setting the key 'required' to true you will require an upload to be made if the Model key is present in the saveAll function. This setting is false by default.
Now anywhere in your app if you attempt to preform a $this->saveAll($data, array('validate' => 'first')); with the file model set as an associative key, an uploaded file will be required as well. If no file is detected during that saveAll the entire save is exited and a validation error occurs.
maxfilesize setting
maxFileSize is a new key setting that allows a developer to limit the size of an upload (note: this does *not* overwrite the limit set in php.ini). This is useful, to tone down the size of uploaded files allowed. The setting takes an int and corresponds to the byte size allowed. If set to false, no file size restrictions (other than those set in php.ini) are enforced on the uploaded file. maxFileSize is false by default.
Example:
- 'maxFileSize' => 102400, //in bytes (~100KB)
- ));
unique setting
Until now, the File Upload Plugin made sure never to overwrite any previously uploaded file. That is still the default behavior, but now you can turn that feature off if you wish.
When unique is set to false, uploaded files will overwrite files on the server with the same name. This setting is true by default.
fileNameFunction setting
We saved the best for last. A much requested feature was the ability to manipulate the resulting filename in a number of ways. Until now, the only way a user could manipulate the file was in a beforeSave(), but that still required the developer to manually rename the file on the server. Some suggested using a sha1 hash, others a md5 hash, and the rest wanted the ability to define their own function to handle the resulting filename. I've decided to make you all happy!
Enter fileNameFunction setting. With this setting you can define your own filename filtering function, or use any built in PHP hashing function.
Examples:
Defining fileNameFunction as sha1, the resulting filename will first be passed into sha1() and then moved to the server and saved to the database. You can use *ANY* PHP function you wish, including functions you define either in bootstrap.php or within your Model.
Bootstrap.php Example:
- //config/bootstrap.php
- function prefix_string($str){
- return 'prefix_' . $str;
- }
- //models/upload.php
- 'fileNameFunction' => 'prefix_string'
- ));
You can also define it within the same Model:
- //models/upload.php
- 'fileNameFunction' => 'sanitizeFileName'
- ));
- function sanitizeFileName($fileName){
- //whatever filename logic you need
- return $fileName;
- }
NOTE: The function you choose must return a string. If the resulting hash function does *not* return a string, the save will be halted and a validation error will occur.
Enjoy v5.0
I hope you enjoy the new features. As always, comments are appreciated. If you enjoy the plugin and wish to help keep it supported, please consider a donation (or click an ad a few times. :) ).
Enjoy,
Nick

V5.0 and fileNameFunction
My Model is as follows:
class Technique extends AppModel {
var $name = 'Technique';
var $actsAs = array('FileUpload.FileUpload'=> array(
'uploadDir' => 'technique',
'allowedTypes' => array('application/pdf'),
'fileNameFunction' => 'sanitizeFileName'
)
);
function sanitizeFileName($fileName){
$sanitized = preg_replace('/[^a-zA-Z0-9-_\.]/','', $filename);
return $sanitized;
}
}
What am I doing wrong? I process the filename through a simple regex function to make sure I got it straight. Still, the uploaded file is left untouched.
Thanks for your help.
Ya, you're returning null.
Try this:
Hope that helps,
Nick
Me->dumb!
LOL no worries.
Nick
Using no model and multiple files
first things first, thanks for the plugin, it's saved me a lot of time. I am trying to use the plugin without model and I am having a few issues, maybe you can give me a hand. I am kinda new to cakephp and I am still learning.
I only need to save the URL of the uploaded files in my database so I think I don't need to use a model for that. I configured the controller like this:
var $helpers = array('Html','Form','FileUpload.FileUpload');
var $components = array('FileUpload.FileUpload');
function beforeFilter() {
$this->FileUpload->fileModel(null);
$this->FileUpload->uploadDir('images/uploads');
}
Then in my view, I have a form with 2 file fields where the user can upload one, two or none graphics files. This is my view code:
echo $form->create(null, array ('url' => array('controller' => 'contenidos', 'action' =>'edit'), 'type' => 'file' ));
echo $fileUpload->input(array('model' => false));
echo $fileUpload->input(array('model' => false));
echo $form->end();
The problem is that if I don't upload both images, after do submit, the controller drops this error:
Warning (512): FileUpload::processFile() - Unable to save temp file to file system. [APP/plugins/file_upload/controllers/components/file_upload.php, line 402]
Also another problem that I have, is how to know which file field the user has sent. The first file field in the view is for a big image and the second one is for a small image. I need to distinguish between both in order to do one action or another. I have to add a var in the helper but it didn't work. Any ideas?
Thanks in advance!
Make sure you have webroot/images/uploads chmod 777
You're getting that warning if the component isn't able to move the uploaded file to the destination you wanted. As such, make sure webroot/images/uploads is created and is writable.
In regards to the second problem you're having, wanting to flag an image upload for a particular type, I can't think of a way off the top of my head that doesn't involve a database.
If you were storing your upload records within a database you could flag that image as "large" or "small" by passing in a hidden field within your form. If you were using the behavior/helper method you could do something like this in your view:
Then when saved to a database, CakePHP would keep track of what was a large image and what was a small image. You could also do some fancy stuff with afterSave() in a model to check the actual image size and determine if its large enough for your "big" flag.
But without a database, I suppose you could just flag it however you wanted it via the form, and hope the user follows instructions. Knowing the order helps, you could count how many files were uploaded, and determine by order what file was what. /shrug That's the best solution I can come up with without using a model.
Hope that helps,
Nick
still Unable to save temp file to file system.
have checked that the webroot/images/uploads is created and is writable. images is 777 and owner www-data but still get the error "Unable to save temp file to file system". It is interesting that when I upload both file fields (big and small) I don't get the "Unable to save..." error, that only happens when I upload one image.
Thanks
Typo in view example
$fileUpload->image('filename.jpg', array('width => 250'));
Should be:
$fileUpload->image('filename.jpg', array('width' => 250));
Cheers,
Dave
Thanks dave
Hope all is well,
Nick
Having Trouble with 'Required' setting
I thought I had everything working but I realized the required=true validation rule is not working. I am able to save a product without selecting a file for upload. I've attached snippets from my controller,model, and view files in case you have a moment to take a look.
Thanks!
-Dave
Controller:
if (!empty($this->data)) {
$this->Product->create();
if ($this->Product->saveAll($this->data, array('validate' => 'first')))
Model:
var $actsAs = array(
'FileUpload.FileUpload' => array(
'fileNameFunction' => 'modifyFileName',
'required' => true
)
);
View:
echo $form->create('Product', array('type' => 'file'));
echo $form->input('Product.code');
echo $form->input('Upload.0.file', array('type' => 'file', 'label' => 'Image'));
echo $form->input('Product.price');
Thanks for the info
Hope all is well,
Nick
Support on CakePHP 1.3?
@File Upload Plugin supports CakePHP 1.x
What seems to be the problem?
I'm not so sure
Or may be creating a readme file for cake 1.3
Different documentation isn't necessary.
I'm interested to know what's going on in your app but you haven't given me any clues as to what the issue is.
'not work' is pretty vague and unhelpful. Are you using the Behavior + Helper method, the Component+Helper? Are you configuring the plugin to use a model, no model? How did you configure it? What version are you running? What have you tried specifically to get it working?
I'd love to help, maybe you could email me your code and I can point you in the right direction.
Hope that helps,
Nick
Well.. it works now..
I used model + component.
Any Help Appreciated.
Any help is appreciated.
Thanx.
Problem with file type
Here is my setting in my upload model.
var $actsAs = array(
'FileUpload.FileUpload' => array(
'uploadDir' => 'files',
'fields' => array('name' => 'name', 'type' => 'type', 'size' => 'size'),
'allowedTypes' => array(
'application/msword',
'application/pdf',
'image/jpeg',
'image/gif',
'image/png',
'image/x-png',
'application/x-shockwave-flash',
),
'required' => false, //default is false, if true a validation error would occur if a file wsan't uploaded.
'maxFileSize' => false, //bytes OR false to turn off maxFileSize (default false)
'unique' => true, //filenames will overwrite existing files of the same name. (default true)
'fileNameFunction' => false //execute the Sha1 function on a filename before saving it (default false)
));
I'm also use "beforeFilter" to change upload location in target model for upload.
function beforeFilter(){
parent::beforeFilter();
$this->FileUpload->uploadDir('files\pdf');
}
The upload works fine with JPEG, PNG as it is default type but I can't add another type.
Thanks in advance.
Basic setup help
I have setup the plugin correctly as far as I can see but I am having one small problem.
I have the Upload table/model setup:
class Upload extends AppModel {
var $name = 'Upload';
var $actsAs = array('FileUpload.FileUpload');
}
And I have a table of offers where people can attach a file:
class Offer extends AppModel {
var $name = 'Offer';
var $displayField = 'name';
var $hasMany = array(
'Upload'
);
}
In my controller I have:
if(!empty($this->data)) {
$this->Offer->create();
$this->Offer->set($this->data);
$this->Offer->set('restaurant_id', $restaurant_id);
if($this->Offer->saveAll()) {
$this->Session->setFlash('Saved');
} else {
$this->Session->setFlash('Failed');
}
}
It saved the file to Upload and the Offer, but does not add the upload_id to the offers table.
This controller function is being used from another controller which 'uses' offer. Could this be the problem?
I would be very grateful for any help.
Many thanks!
Antony
Previous comment
Please ignore my last comment! belongsTo not hasMany. Doh!
Fantastic plugin, thanks again!
Model+Component is not a valid setup.
The three options are:
Behavior+Helper, Component+Helper (With Upload Model w/o behavior), or Component+Helper (no model).
You've setup the behavior correctly, as such, you don't need the component.
Hope that helps,
Nick
For Behavior+Helper with different setting
But if I need different setting like Component+Helper that we can use "beforeFilter" to config some setting.
Can we do that? Because I need to upload file into different folder.
But if we can't it is fine I can use Component+Helper anyway...
behavior does not seem to be "triggered"
i have been trying to make the file_upload behavior to work for 2 days and it seems to not being 'called'.
No file uploaded, and i get a sql error because name, type and size are not populated.
Here is my conf :
in app/models/document.php
class Document extends AppModel{
var $name = 'Document';
var $actsAs = array(
'FileUpload.FileUpload' => array(
'uploadDir' => 'picts',
'allowedTypes' => array(
'jpg' => array('image/jpeg', 'image/pjpeg'),
'jpeg' => array('image/jpeg', 'image/pjpeg'),
'gif' => array('image/gif'),
'png' => array('image/png','image/x-png')),
'maxFileSize' => '10000', //bytes OR false to turn off maxFileSize (default false)
'required' => true
));
var $belongsTo = array(
'Post' => array(
'className' => 'Post',
'foreignKey' => 'post_id'
)
);
in app/models/post.php
var $hasMany = array(
'Document' => array(
'className' => 'Document'
),
);
in app/controllers/posts_controller.php
if(!empty($this->data)){
$this->Post->saveAll($this->data, array('validate'=>'first'));
}
in this controller i checked the behaviors with :
$behaviors = Configure::listObjects('behavior');
pr($behaviors);
And only the default package behaviors are showing : Acl, Containable, Translate, Tree.
I'm quite new to cakephp so i don't know what to check to find out where my code is wrong.
Thank you for your help !
error found !
Really annoying when it takes so much time to discover the one typo i made !