File Upload Plugin v4.0 -- Behaviors and Global Settings
Date: Fri, Nov 20th 2009, 20:37 Author: nick Views: 2550 Comments: 56 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
New in version 4.0 of the File Upload Plugin is a new behavior and global settings classes. As most of you who are familiar with File Upload Plugin know, it was rather odd that when you setup the FileUpload component the way you wanted in your controller you then had to set it up again in your view for the helper to send the component the right information. Well, all that is gone with a new global settings class. For those of you not familiar with the File Upload Plugin, if you are developing a site that allows a display picture or avatar, perhaps one similar to http://www.partypoker.com/ you will know dealing with uploads can be tricky. Hopefully this plugin will clear up any issues you may have.
Settings you save in plugins/file_upload/config/file_upload_settings.php will be the new "default" settings across all your file uploading instances. This is true for the component, the helper, and the new behavior. By opening up this settings file you'll see all the documentation on what each setting does and how to manipulate it.
All the settings are there: fileModel, fileVar, uploadDir, allowedTypes, fields, automatic, and massSave (new since 3.6)
Due to the new way we handle our settings globally, setting and retrieving our settings has slightly changed. The full migration guide is included in the most recent version of this plugin (file_upload/migration_guide_3_x-4_0.txt), but I'll go over the change briefly as its very straight forward.
OLD WAY:
NEW WAY:
As you can see, each setting has been given its own method (actually its a __call overload so you can create your own settings if you'd like). By not passing in any parameters to the setting's method it will return the current value of that setting. If you then pass in a value to the setting's method you'll then be setting that setting (that's fun to say). I think an example will help explain:
OLD WAY:
NEW WAY:
As you can see, by passing in a value to that setting's method you'll now be setting that specific option.
Legacy Plugin: I've stamped the latest version without these API changes and without the behavior or global settings to 3.6.3. I will be keeping this legacy plugin for those who wish to stay with the old way of doing things. Get the legacy plugin v3.6.3 here: http://projects.webtechnick.com/file_upload_plugin_v3_6_3.tgz
New in 4.0 is a great behavior to attach to your model. By using this behavior you will no longer need the component. I've left the component in, for legacy reasons, as well as its the only way to preform file uploads without a model (one of my main goals when developing this project).
The behavior is extremely flexible and easily fits into your current project allowing for automagic file uploading without you having to think about it. Setup is simple:
Attach the FileUpload.FileUpload to your model of choice, we'll use our trusty Upload model as an example...
Simple as that, now whenever you (or another associated model) save an upload with a file submitted, a record will be saved and all your file related columns (name,size,type) will be filled in for you automatically. The plugin takes special care not to overwrite files.
As discussed before, all the settings will be inherited by the new settings class located in /plugins/file_upload/config/file_upload_settings.php, but that doesn't mean you can't pass in your own settings on the fly. Using our same Upload model, lets change the save directory to 'uploads', our column names from name,size,type to file_size,file_size,file_type, lets only allow .pdfs to be uploaded, lets make it so an upload is required (required is new in 4.2.x), and only allow less than 10KB files (new in 4.3).
All set, all the default settings are the same except we're now uploading to the 'uploads' directory (app/webroot/uploads), we've changed our file specific columns from name, type, and size, to file_name, file_type, and file_size, we require a file to be uploaded, our max file size to allow is 10,000 bytes, and finally we're only allowing .pdf files to be uploaded and saved as new records.
Doing the upload is just as simple in the view, here's an example:
Doing your file uploading this way with a behavior lets you build your associations with full upload support without hesitation. Continuing with our example lets say we have an Application model that hasMany Uploads.
Assuming Application->hasMany->Uploads, in views/applications/add.ctp :
Notice we're just using normal cakePHP association syntax in our view, just be sure to use saveAll() instead of save() in your application controller add function. =)
The new behavior will automatically delete the source file when the record of that upload has been deleted. No more worrying if you have old crusty files hanging around your file system long after any record of it ever exists. =)
That's it for version 4.0. There's more to look over in the API and in the actual code itself if you'd like to learn more.
API: http://projects.webtechnick.com/docs/file_upload_plugin
Thanks, I hope you all find it useful! As always, if you like the plugin, find a bug, or have a feature request -- post a comment. =)
Nick
Settings you save in plugins/file_upload/config/file_upload_settings.php will be the new "default" settings across all your file uploading instances. This is true for the component, the helper, and the new behavior. By opening up this settings file you'll see all the documentation on what each setting does and how to manipulate it.
All the settings are there: fileModel, fileVar, uploadDir, allowedTypes, fields, automatic, and massSave (new since 3.6)
API changes...
Due to the new way we handle our settings globally, setting and retrieving our settings has slightly changed. The full migration guide is included in the most recent version of this plugin (file_upload/migration_guide_3_x-4_0.txt), but I'll go over the change briefly as its very straight forward.
GETTING YOUR SETTINGS:
OLD WAY:
- $this->FileUpload->fileModel;
- $this->FileUpload->fileVar;
- $this->FileUpload->fields;
NEW WAY:
- $this->FileUpload->fileModel();
- $this->FileUpload->fileVar();
- $this->FileUpload->fields();
As you can see, each setting has been given its own method (actually its a __call overload so you can create your own settings if you'd like). By not passing in any parameters to the setting's method it will return the current value of that setting. If you then pass in a value to the setting's method you'll then be setting that setting (that's fun to say). I think an example will help explain:
SETTING YOUR SETTINGS:
OLD WAY:
- $this->FileUpload->fileModel = null;
- $this->FileUpload->fileVar = 'file';
NEW WAY:
- $this->FileUpload->fileModel(null);
- $this->FileUpload->fileVar('file');
As you can see, by passing in a value to that setting's method you'll now be setting that specific option.
Legacy Plugin: I've stamped the latest version without these API changes and without the behavior or global settings to 3.6.3. I will be keeping this legacy plugin for those who wish to stay with the old way of doing things. Get the legacy plugin v3.6.3 here: http://projects.webtechnick.com/file_upload_plugin_v3_6_3.tgz
Behaviors for the WIN!
New in 4.0 is a great behavior to attach to your model. By using this behavior you will no longer need the component. I've left the component in, for legacy reasons, as well as its the only way to preform file uploads without a model (one of my main goals when developing this project).
The behavior is extremely flexible and easily fits into your current project allowing for automagic file uploading without you having to think about it. Setup is simple:
Attach the FileUpload.FileUpload to your model of choice, we'll use our trusty Upload model as an example...
- class Upload extends AppModel {
- var $name = 'Upload';
- }
Simple as that, now whenever you (or another associated model) save an upload with a file submitted, a record will be saved and all your file related columns (name,size,type) will be filled in for you automatically. The plugin takes special care not to overwrite files.
As discussed before, all the settings will be inherited by the new settings class located in /plugins/file_upload/config/file_upload_settings.php, but that doesn't mean you can't pass in your own settings on the fly. Using our same Upload model, lets change the save directory to 'uploads', our column names from name,size,type to file_size,file_size,file_type, lets only allow .pdfs to be uploaded, lets make it so an upload is required (required is new in 4.2.x), and only allow less than 10KB files (new in 4.3).
- class Upload extends AppModel {
- var $name = 'Upload';
- 'uploadDir' => 'uploads',
- 'name' => 'file_name',
- 'type' => 'file_type',
- 'size' => 'file_size'
- ),
- 'requilred' => true,
- 'maxFileSize' => '10000',
- )
- );
- }
All set, all the default settings are the same except we're now uploading to the 'uploads' directory (app/webroot/uploads), we've changed our file specific columns from name, type, and size, to file_name, file_type, and file_size, we require a file to be uploaded, our max file size to allow is 10,000 bytes, and finally we're only allowing .pdf files to be uploaded and saved as new records.
Doing the upload is just as simple in the view, here's an example:
Doing your file uploading this way with a behavior lets you build your associations with full upload support without hesitation. Continuing with our example lets say we have an Application model that hasMany Uploads.
Assuming Application->hasMany->Uploads, in views/applications/add.ctp :
Notice we're just using normal cakePHP association syntax in our view, just be sure to use saveAll() instead of save() in your application controller add function. =)
Automagic File Upload Deletions...
The new behavior will automatically delete the source file when the record of that upload has been deleted. No more worrying if you have old crusty files hanging around your file system long after any record of it ever exists. =)
That's it, enjoy the new features!
That's it for version 4.0. There's more to look over in the API and in the actual code itself if you'd like to learn more.
API: http://projects.webtechnick.com/docs/file_upload_plugin
Thanks, I hope you all find it useful! As always, if you like the plugin, find a bug, or have a feature request -- post a comment. =)
Nick

change to checkType
function checkType($file = null){
$this->setFile($file);
foreach($this->options['allowedTypes'] as $value){
if(strtolower($this->file['type']) == strtolower($value) || $value == '*'){
return true;
}
}
$this->_error("Uploader::_checkType() {$this->file['type']} is not in the allowedTypes array.");
return false;
}
Thanks for the contribution
To allow all upload mime types you can use
Hope all is well,
Nick
Resize
Is there any chance to resize the image and also create a thumbnail while uploading it. If it supports, how can I do that? I'm using the behaviour uploading and not the component one.
Cheers.
Amirul.
Hi Amirul
That will resize the uploaded image and save the resized image to your resized directory as specified by the helper.
I'll add your request to the *wish list* for future releases.
Hope all is well,
Nick
Helper not helping
I did what you have suggested but don't really work. I got this error after I tried to upload/save it:
Warning (4096): Argument 1 passed to Upload::afterSave() must be an instance of boolean, boolean given, .....
Warning (2): Cannot modify header information ...
I'm not sure where I did wrong but for some reasons the images didn't save to the 'resized' directory (the 'resized' dir has set chmod 777).
FYI, I have also tried what you have suggested on the image resizing comments at http://www.webtechnick.com/blogs/view/221/CakePHP_File_Upload_Plugin It also not working for me. It seems that the helper don't do the job. Do you have any suggestions where am I missing?
Thanks a lot.
chmod
Images should be 644.
Can you view the image normally in your browser?
Some hacks
1) I needed support for hasOne relationships - where a model only had one image lets say - so I added some logic to the behavior to find and delete all Uploads associated with a foreign_key before saving. This was tricky and my code isn't that great, I'm sure you might be able to figure out a better way off adding this feature in.
2) I also like to keep width/height information in my tables so I can add that information to the HTML directly, so I added some logic to Class Uploader at line 90:
//now move the file.
if(move_uploaded_file($this->file['tmp_name'], $target_path)){
// Get image metadata
$meta = @getimagesize($target_path);
$this->finalFile = basename($target_path);
$output['height'] = $meta[1];
$output['width'] = $meta[0];
$output['meta'] = $meta[3];
$output['filename'] = $this->finalFile;
return $output;
}
Thanks
You might consider moving that code into a beforeSave() callback in your upload model that set the height/width/meta keys in your $data array before the final save. That would make you're needed code separate from the plugin (allowing for easy upgrades and such). Just something to consider.
Thanks for sharing, and the kind words. =)
abhishek chowla
my images are getting stored on server with original size and resized. but it throws me error as mentioned below
Warning (4096): Argument 1 passed to Upload::beforeSave() must be an instance of boolean, array given, called in /opt/lampp/htdocs/abhishek/projlibrary_cake/cake/libs/model/model.php on line 1193 and defined [APP/models/upload.php, line 7]
Code
var $actsAs = array('FileUpload.FileUpload'=> array('uploadDir' => 'files'));
function beforeSave(boolean $created)
Upload::beforeSave() - APP/models/upload.php, line 7
Model::save() - CORE/cake/libs/model/model.php, line 1193
Model::__save() - CORE/cake/libs/model/model.php, line 1658
Model::saveAll() - CORE/cake/libs/model/model.php, line 1562
FileUploadComponent::processFile() - APP/plugins/file_upload/controllers/components/file_upload.php, line 291
FileUploadComponent::processAllFiles() - APP/plugins/file_upload/controllers/components/file_upload.php, line 347
FileUploadComponent::startup() - APP/plugins/file_upload/controllers/components/file_upload.php, line 184
Component::startup() - CORE/cake/libs/controller/component.php, line 112
Dispatcher::_invoke() - CORE/cake/dispatcher.php, line 210
Dispatcher::dispatch() - CORE/cake/dispatcher.php, line 194
[main] - APP/webroot/index.php, line 89
Notice (8): Undefined property: FileUploadHelper::$Html [APP/plugins/file_upload/views/helpers/file_upload.php, line 270]
Code | Context
$image = "/files/resized/mapdatax100.gif"
$options = array()
}
else {
return $this->Html->image($image, $options);
FileUploadHelper::_htmlImage() - APP/plugins/file_upload/views/helpers/file_upload.php, line 270
FileUploadHelper::_getImageByName() - APP/plugins/file_upload/views/helpers/file_upload.php, line 211
FileUploadHelper::image() - APP/plugins/file_upload/views/helpers/file_upload.php, line 94
Upload::beforeSave() - APP/models/upload.php, line 21
Model::save() - CORE/cake/libs/model/model.php, line 1193
Model::__save() - CORE/cake/libs/model/model.php, line 1658
Model::saveAll() - CORE/cake/libs/model/model.php, line 1562
FileUploadComponent::processFile() - APP/plugins/file_upload/controllers/components/file_upload.php, line 291
FileUploadComponent::processAllFiles() - APP/plugins/file_upload/controllers/components/file_upload.php, line 347
FileUploadComponent::startup() - APP/plugins/file_upload/controllers/components/file_upload.php, line 184
Component::startup() - CORE/cake/libs/controller/component.php, line 112
Dispatcher::_invoke() - CORE/cake/dispatcher.php, line 210
Dispatcher::dispatch() - CORE/cake/dispatcher.php, line 194
[main] - APP/webroot/index.php, line 89
Fatal error: Call to a member function image() on a non-object in /opt/lampp/htdocs/abhishek/projlibrary_cake/app/plugins/file_upload/views/helpers/file_upload.php on line 270
so please give some time and le me know the solution, thanks in adv
Email me your code
At first glance it looks like you're using the component and the model behavior at the same time. You should use one or the other as using both will cause collisions and duplicate records.
Hope that helps,
Nick
Using plugin inside a form related to a different model (not upload.ctp)
I would like to ask you if/how it is possible to use your great plugin inside a form related to a different model (not upload.ctp) by using saveall()...
Let me show you a simplistic case I'm experimenting on:
I have two database table:
CREATE TABLE IF NOT EXISTS `posts` (
`id` int(11) unsigned NOT NULL auto_increment,
`title` tinytext NOT NULL,
`created` datetime default NULL,
`updated` datetime default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `uploads` (
`id` int(11) unsigned NOT NULL auto_increment,
`name` varchar(200) NOT NULL,
`post_id` int(11) NOT NULL,
`type` varchar(200) NOT NULL,
`size` int(11) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
where post-HASMANY-upload and upload-BELONGSTO-post
So here are the two models:
app/models/post.php
class Post extends AppModel {
var $name = 'Post';
var $hasMany= array('Upload');
var $validate = array(
'title' => array('rule' => array('notEmpty'))
);
}
?>
app/models/upload.php
class Upload extends AppModel {
var $name = 'Upload';
var $actsAs = array('FileUpload.FileUpload');
var $belongsTo = array('Post');
var $validate = array(
'name' => array('rule' => 'notEmpty')
);
}
?>
Now, if possible, I would like to have a form where in the view action add.ctp for the post model i also include the uploading field... to achieve this goal I have try with the following posts_controller.php and add.ctp view action:
app/controllers/posts_controller.php
class PostsController extends AppController {
var $name = 'Posts';
var $helpers = array('Html', 'Form');
function index() {
$posts = $this->paginate();
if(isset($this->params['requested'])) {
return $posts;
}
$this->set('posts', $posts);
}
function add() {
if(!empty($this->data)) {
$this->Post->saveAll($this->data, array('validate'=>'first'));
}
}
}
?>
app/views/posts/add.ctp
create('Post');?>
//echo $form->create('Upload', array('type' => 'file'));
echo $form->input('Upload.name');
echo $form->input('Upload.0.file', array('type' => 'file'));
echo $form->input('Upload.1.file', array('type' => 'file'));
//echo $form->end('Save Upload and Two Uploads');
?>
end('Submit');?>
Like this I don't get any particular errors, but only the following partial results:
- posts data are all saved correctly to the database
- for uploads, only the field 'name' is saved (with '1' as prefix !?!)
- no photos are actually uploaded to the proper location app/webroot/files
This is it... what do you think ? Can you maybe see any evident wrong sides in this method ? Do you think it's praticable in a different way ?
Thanks a lot in advance for any useful advice
Best Regards
deepz
Looks like you're not sending the file with the upload
//add.ctp
Good luck,
Nick
works perfectly !
Thanks a lot Nick !
deepz
Duplicate record
Thanks
Email me your code
Most likely you're calling $this->save in your controller when you don't have to (if you're using the component). Or you don't have your form setup correctly (if you're using the behavior approach). Or both. Hard to tell you what's going on exactly without seeing what you're doing.
Hope that help,
Nick
This is what i have
var $components = array('FileUpload.FileUpload');
function beforeFilter() {
parent::beforeFilter();
$this->FileUpload->uploadDir('files/publications');
$this->FileUpload->fields(array('name'=>'name', 'type' => 'type', 'size' => 'size'));
$this->FileUpload->fileModel('Upload');
//$this->FileUpload->allowedTypes(array('application/pdf'));
$this->FileUpload->massSave(true);
}
function add() {
if (!empty($this->data)) {
//this->Publication->create();
if($this->FileUpload->success ){
//$this->Session->setFlash('Save Successfull!');
//$images = $this->FileUpload->uploadIds;
//$this->Publication->saveField('upload_id', $images[0]);
$this->Session->setFlash(__('The Publication has been saved', true));
$this->redirect(array('action'=>'index'));
}
else { $this->Session->setFlash($this->FileUpload->showErrors());
}
}
}
In add.ctp, I have:
?php echo $form->create('Publication', array('enctype' => 'multipart/form-data'));?>
end('Submit');?>
Looks correct, but use behavior if using model.
If you're using a model, I suggest using the behavior instead of the component (the component is depreciated and is only kept in the plugin to allow for non-model use).
For your configuration I'd add this to your Upload model
Then just remove the FileUpload.FileUpload from your components array and change your add action to something like this:
Keep your view the way it is. That should get you what you expect.
Hope that helps,
Nick
Nice!! It works fine now
Excellent plugin
Behaviour works like a charm. I was able to use it with my model that has quite a few other properties (besides the required 3).
Any tips on how to use the bundled RResizeImage class? I see it's interface in docs, but how to use it within CakePHP framework (and/or FileUpload module)?
Just can't figure out how to start.
RResizeImage is a utility for FileUploadHelper
If you want direct access to the RResizeImage class from somewhere else in your app you'll have to import FileUploadHelper and then instantiate it.
That should get you what you want. But like I said, I don't suggest using it directly. Let the FileUploadHelper do the work for you on the fly.
Thanks for the kind works,
Nick
Thanx
But can i use the helper to serve thumbnails (really) on the fly, without saving them on server? I'll need various thumb sizes in various parts of the app., so i don't want to save all the sizes to disk, espec. since the sizes' cpecs might change in the future.
Use Browser resizing if filesystem is not an option.
If you (really) don't want to save the resulting thumbnail to disk I suggest just use the browser to resize your photos on the fly. Your users will still have to download the large file, but they wont have to wait for a GD library resize of the file on top of that request.
The primary feature of the FileUploadHelper is the image function, it will resize your photo and save it to your filesystem for immediate retrieval 'next-time'. Your first request might take a second or two, but the next one will be a fraction of that.
Hope that helps,
Nick
it's not really the same
I've tested, and browser-resizing (i.e. loading original images) is about 5 times slower than getting a GD generated thumbnail (with no caching).
The thing is, sometimes i'm building sites which use thumbnails in teh site, and then i do create thumb files. But sometimes the site itself doesn't need thumbs; i only need them in CMS (for more user-friendly image-maintenance), so i wanted to avoid creating thumbnails on server when they will be very rarely accessed, and only by the site admin. That's why i wanted on-the-fly generation.
But be that as it may, when i try your solution, it doesn't work. The afterSave function you suggested above doesn't create any thumbnails, and "echo $fileUpload..." doesn't output anything :/
It's not totally clear to me how to use it. In afterSave function the image function seems void (i.e. the output is not assigned to any var), but it does have a 'imagePathOnly' option!? While in your last example it seems to generate a tag.
If you could explain how to use it exactly, you would help me a lot. I'm not (usually) the type who asks for help from class authors, but it's now the second day i'm losing just to get thumbnails shown in ANY way (i've tried 2 other solutions besides your class but to no avail)
Sorry to bother you, but i'm startinig to pull my hair out over this.
Thanks in advance.
nota bene...
Helpers are typically exclusive to views.
In terms of using the Helper in an afterSave. The afterSave example is not a typical use of any helper, it was an example of how to create a resized image immediately after the user submits an image -- to bypass the slight performance hit the next time (ie first time) a user wishes to view that image smaller.
However, that's not the typical use. Typically a helper is used exclusively in views. Those examples in my previous comment are code snippets in a view, not the afterSave() function in a model.
I can see why you might be confused, but I hope that clears things up. The imagePathOnly option is helpful for javascript/ajax features that require the path of a generated thumbnail, as such an img tag isn't produced. In the case of the afterSave() method we don't care about the return value, only that the resizing happened as a byproduct of calling $FileUpload->image(...).
In the end its up to you how you want to handle your thumbnails. I've always found that diskspace is cheap, ram/cpu is expensive in the hosting world.
Hope that helps,
Nick
Digging through past blogs
http://www.webtechnick.com/blogs/view/205/2_0_1_FileUploadHelper_Released
There are also more examples of view/controller/model relationships via the more generic Plugin blog here:
http://www.webtechnick.com/blogs/view/221/CakePHP_File_Upload_Plugin
Error for Max Size
Checking out
In the meantime, i've managed to have afterSave callback work, but when i try to echo/output the tag, upload helper "claims" it's Html helper is null, be it as $this->Html or $html var. Strange, it's listed in $helpers array, and it doesn't help even if i App::import it literally.
I'll keep you posted when i figure out what may be wrong.
PS. Re GD etc: reading large image + generating a thumb may take a few ms longer than just reading, but 2 Kb still takes a lot less to _travel_ than 700 Kb :).
Validation new in 4.1.0
afterSave()
Again, I don't recommend doing this for everyone else following the comments. Use the FileUploadHelper the way it was meant to be used -- in a view. =)
not echoing in model but in view
afterSave is just the 1st of 2 things that i succeeded in making work.
Thanx for the tip to explicitly instantiate Html helper (and not only import). I think i read somewhere that even just listing a helper in $helpers array should be enough to have a instance available; same with App::import-ing one; but apparently it's not so.
So now that i did instantiate Html helper, i have it output the tag finally - but with a small bug:
it was outputing e.g.
img/\img\resized\imagenamex150.jpg
instead of /img/resized/imagenamex150.jpg
(as you may notice, i'm developing locally on Win machine)
so after i fixed that in my view (didn't want to tamper with your helper in case there'll be upgrades), i have it finally working.
I've now removed the whole afterSave part in the model, as everything now works ok without it.
Thanx again for your help and sorry for lost time! :)
You're a great guy, God bless you.
You found a bug. Thanks!
I'll post a patch soon after this post.
In regards to the Helpers array you should indeed only have to add FileUpload.FileUpload into the helpers array of your controller.
Doing that will grant access to $fileUpload in a corresponding view that will have Html instantiated for you already. You only have to do it by hand if you're App::import'ing FileUploadHelper by hand. Hope that makes sense.
Thanks for the catch on the windows server. I'll patch that ASAP.
4.1.1 Fixed Windows Server Image Paths
Thanks again for the catch,
Nick
there's two parts to the bug...
First is indeed the DS version, and second is that the html helper was adding the default img/ to the front of the $image path, which already had it's /img/ part added (i guess coming from options['uploadDir'])
Hmm...
I'll have to look into that.
By default the files will be uploaded to /webroot/files/ to keep separation between your website /img and uploaded files.
exactly
I have upload dir set to img because i'm using it in CMS, to add images to the site/page.
resize not working
i have used component method 4 uploading files and files are getting saved to desired folder correctly .But when im trying to tresize them using afterSave it doesno works i.e. file is not resized and not saved in resized folder.
What does your afterSave() function look like?
Validation
my save looks like this
if($this->Upload->saveAll($this->data,array('validate' => 'first'))){ //stuff }
When i try to do a save with a file type not allowed I get a warning at the top
Warning (512): Uploader::_checkType() application/vnd.openxmlformats-officedocument.spreadsheetml.sheet is not in the allowedTypes array. [APP/plugins/file_upload/vendors/uploader.php, line 133]
When I try a file that is too big, nothing even happens, just forwards back to the page with no status messages.
not sure how to debug this.
Validation errors only work when using the Behavior
However, you should be receiving the UPLOAD_ERR_INI_SIZE (int of 1) error if your file is outside the range of what your PHP configuration allows.
To debug I suggest putting a debug($this->data) before your save to see what error code PHP thinks its getting.
Good luck,
Nick
RE: Validation errors only work when using the Behavior
Love it
I have only one issue now, my upload table contains 5 fields and during multi-upload I want to specify an additional comment for that particular row.
I can't seem to find a way to achieve that. I got the reference column to the master database through association. Is there a way for me to be able to add additional columns to the model?
Thanks for the kind words
An example of this might be:
The above example will save the comment with its associated file upload.
Hope that helps,
Nick
Validation
Is there a way to only validate the file? I mean, there is no saving after it validates like $this->Model->validates(). Because i want to use ajax to check the file first if it validates and display a check beside the file field.
Can't send files through Ajax
Unfortunately, a user will have to submit the file, because you cannot send a file through an XHR (ajax). You can mimic ajax with iframes or flash, but it's not ajax, and you're still sending the file. It's a limitation of javascript.
I know a lot of developers complain about that limitation, but I'm happy its there. Otherwise, nothing would stop developers from creating scripts that could scan our hardrives looking for specific files and upload them without us knowing. I for one am glad Javascript cannot open and send files without human interaction. :)
Hope that helps,
Nick
Ajax
I'm not going to send it through ajax. I just want to use ajax in validation, no saving yet.
By the way, how can I set the max size of the file?
Thanks,
Maurelle Mejos
@Maurelle
Filesize limit
In my previous project, I was able to restrict every users to upload only images that does not exceed 1mb by checking the size in the file array.
I hope you will include this in your next version Nick. This is very important to prevent our users from uploading huge files.
Thanks,
Maurelle Mejos
Version 4.3 update
I suggest using it like so:
Have fun and thanks for the suggestion,
Nick
up to .ini restriction or above?
or only up to this limit?
maxFileSize up to .ini restriction
max_upload_filesize is a PHP limitation, whereas maxFileSize is a CakePHP Validation limitation.
Hope that helps,
Nick
no errors but file did not upload
- create database table
CREATE TABLE IF NOT EXISTS `filedownloads` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title_ina` varchar(255) NOT NULL,
`title_eng` varchar(255) DEFAULT NULL,
`body_ina` text NOT NULL,
`body_eng` text,
`filedownloadtype_id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`type` varchar(255) DEFAULT NULL,
`filesize` int(11) DEFAULT NULL,
`created` datetime DEFAULT NULL,
`modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
- copy file_upload.php to app/model/behaviors
- copy file_upload.php to app/controller/component
- copy uploader.php to app/vendors
/*this is my model*/
class Filedownload extends AppModel {
var $name = 'Filedownload';
var $validate = array(
'title_ina' => array('notempty'),
'body_ina' => array('notempty'),
'filedownloadtype_id' => array('numeric'),
'name' => array('notempty')
);
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $belongsTo = array(
'Filedownloadtype' => array(
'className' => 'Filedownloadtype',
'foreignKey' => 'filedownloadtype_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
var $actsAs = array(
'FileUpload.FileUpload' => array(
'uploadDir' => 'files',
'fields' => array('name' => 'file_name', 'type' => 'file_type', 'size' => 'file_size'),
'allowedTypes' => array('application/pdf'),
'required' => true, //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)
)
);
}
?>
and this is my filedownloads/add.ctp file
create('Filedownload', array('type' => 'file'));?>
end('Submit');?>
everything is working fine but the file did not upload to my server, is there anything wrong? , please need your guide
No need to copy to behaviors/components/helpers
There is no need to copy the related files to your app. The plugin is self containing (like all CakePHP plugins. Simply drop the 'file_upload' directory into your /app/plugins/ directory and then proceed with your steps.
Hope that helps,
Nick
the resized folder
does the resized folder gets created own its own??
if a create the folder manually then also the resized image does not gets created.
What am i missing?
Resized folder does not get created on its own
The resize element of the plugin needs to have the GD library installed to work, otherwise the fallback is browser resizing (ie setting width/height to what it would have been).
Hope that helps,
Nick