Recent Thoughts

Downloads

Contact Us

Email:
Topic:
Message:

Google Ad

FileUpload Plugin v3.5 -- Multiple File Uploads

Date: Fri, Oct 30th 2009, 17:24 Author: nick Views: 3774 Comments: 10 share

CakePHP File Upload Plugin

Info:
Get it:
  • Download Now
  • svn co http://svn.github.com/webtechnick/CakePHP-FileUpload-Plugin file_upload
The newest release of File Upload Plugin is now here -- version 3.5 and includes the much asked for multiple file Upload support through the helper and component.

First the Nitty Gritty.... API Changes


There are some API changes that are involved with this new version, but I've done my best to backport all the changes so the plugin will work exactly as before if you aren't interested in multiple file uploads and change nothing in your app.

New Additions

  • FileUpoad::uploadIds array of created Upload ids
  • FileUpoad::finalFiles array of created Upload names
  • FileUpoad::processAllFiles is done automatically, but if you've set FileUpload::automatic to false in a before filter you'll need to use the new processAllFiles() function instead.


Deprecated

  • FileUpload::uploadId is now depreciated, use $this->FileUpload->uploadIds instead.
  • FileUpoad::finalFile is now depreciated, use $this->FileUpload->finalFiles instead.
  • FileUpoad::processFile is now depreciated, use $this->FileUpload->processAllFiles() instead.


Even though uploadId and finalFile are depreciated now, they will still work as expected with only a single file uploaded. However, if you're uploading multiple files, uploadId and finalFile will represent the *last* file in the sequence of files that was uploaded.

Example:
Lets say I've uploaded two images -- image-1.jpg and image-2.jpg -- as a multiple-file upload. Using finalFile would only return image-2.jpg (not image-1.jpg). But I can now use finalFiles as an array of files that were uploaded, like so:
  1. echo $this->FileUpload->finalFile; //returns 'image-2.jpg'
  2.  
  3. //But since I uploaded two images I can see them both through the finalFiles array
  4. echo $this->FileUpload->finalFiles[0]; //returns 'image-1.jpg'
  5. echo $this->FileUpload->finalFiles[1]; //returns 'image-2.jpg'


The same is true for uploadId vs uploadIds.

One final API change is the direct access to processFile function. Before you could set $this->FileUpload->automatic = false; in a before filter and later call processFile(); on your own. You can still do that, but it will only process the first file uploaded -- nothing more. To make sure you process all files in the queue, you'll need to use processAllFiles(); instead. An example of that would be:
  1. /*Assuming you have
  2.   $this->FileUpload->automatic = false;
  3.   in a before filter. */
  4. if ($this->FileUpload->hasFile) {
  5.     $this->FileUpload->uploadDir = 'files/sub/dir/1/2/3';
  6.     $this->FileUpload->processAllFiles();
  7. }


Now On to the Cool Bits...


So now we have all the API changes out of the way, let me show you some tricks I've cooked up with the Helper to make your Multiple File Uploading life easier.

I've re-factored the FileUploadHelper::input() so that you can call it multiple times and all the right magic will work for multiple files.

Example:
  1. echo $fileUpload->input();
  2. echo $fileUpload->input();
  3. echo $fileUpload->input();


Simply calling input() three (or any number) times will build you all the necessary form elements you need to upload three (or any number) of files at the same time. Of course all the same options are available to you, as well as any option that is available to the FormHelper::input() function as the helper will pass along the options as needed.

Not to fret non-model users, I didn't forget about you. =) The new multiple file upload works with non-model as well. Again, let the helper do the work for you:

Example:
  1. echo $fileUpload->input(array('model' => false));
  2. echo $fileUpload->input(array('model' => false));
  3. echo $fileUpload->input(array('model' => false));


Again, all the hard work is done for you. For those of you who don't like using helpers (for whatever reason). The new syntax for non-model multiple file upload fields are as followed: data[file][0], data[file][1], data[file][2], etc...

That's It.... Have fun!


I hope you all enjoy the new changes and features. As always, if you like the plugin, find a bug, or have a feature request -- post a comment. =)

Comments

10/31/2009 4:50 am

help

hi nick i get this error with version 3.5:
Fatal error: Cannot use string offset as an array in \app\plugins\file_upload\controllers\components\file_upload.php on line 477
10/31/2009 10:08 am

Hmmm...

What PHP version are you running by chance? I've read that was a bug in PHP 5.1.1.
10/31/2009 11:20 pm

help relationship

Hi Nick, I am a begginer in cakephp and would like your help here.. I am trying use your plugin to upload the images of my products controller.. I would like save the product_id in the uploads table, but when I change to saveAll, the rest of data (name, type, size) save as empty. Should I change the code of processFile() directly in the component and add this field? Thank you.
11/01/2009 1:03 am

I'm happy to help

The File Upload Component will save any data along with the upload itself for you automatically, you don't need to call save() or saveAll() yourself, just add the appropriate product_id into the the upload form.

Example:
  1. echo $form->create('Upload', array('type' => 'file'));
  2. echo $form->input('product_id');
  3. echo $fileUpload->input();
  4. echo $form->end('Submit');


Upon successful upload the product_id specified by the form element will be placed into the uploads table. This will all be done for you by the component, no need to do anything else in your controller. Your controller might look something like this:

  1. function add(){
  2. if(!empty($this->data)){
  3.   if($this->FileUpload->success){
  4.     $this->Session->setFlash('File Uploaded!');
  5.   }
  6.   else {
  7.   $this->Session->setFlash($this->FileUpload->showErrors());
  8.   }
  9. }
  10. }


As you can see you don't need to do anything more, the component takes care of the save for you.

If you want to do an edit, without a file being uploaded you'll have to do something like this:
  1. function edit($id = null){
  2.   if(!empty($this->data)){
  3.     if($this->FileUpload->success || $this->Upload->save($this->data)){
  4.       $this->Session->setFlash('You updated!');
  5.     }
  6.     else {
  7.       $this->Session->setFlash('Error, try again.');
  8.     }
  9.   }
  10.   if(empty($this->data)){
  11.     $this->read(null, $id);
  12.   }
  13. }


Notice you're only doing one or the other, either the FileUpload is doing the creation with a new upload (if so the save() call is shortcutted and never called) or the model is doing the update because a file wasn't uploaded.

If that explanation doesn't help, I suggest emailing me your code so I can take a look at what you're trying to do.

Hope that helped,
Nick
11/04/2009 12:17 pm

missing component error

Hey Nick, sorry to bother...
I´m still starting with cakephp. I followed all the instructions but I keep getting an error "component file missing" although I included FileUpload.FileUpload to my helpers and components array in my controller.
Any help would be great. Keep up the good work, seems you have a good thing going here!
Thanks!
11/04/2009 5:11 pm

nevermind

it took some time to look through this. the folder from the download package is called file_upload_plugin and had to be renamed to match conventions to file_upload.
I'll play around with it now.
11/05/2009 5:42 am

ininitialized string offset - PHP Version 5.2.11

I´m getting the same error here. Can't figure out what went wrong. Here's the error message:

Notice (8): Uninitialized string offset: 0 [APP/plugins/file_upload/controllers/components/file_upload.php, line 477]

Code | Context

$retval = array(
array(
"file" => "preview_arcade_sign.jpg"
),
array(
"file" => ""
),
array(
"file" => ""
),
array(
"file" => ""
),
array(
"file" => ""
)
)
$file = array(
"file" => ""
)
$key = 1

if($retval){
foreach($retval as $key => $file){
if($file[$this->fileVar]['error'] == UPLOAD_ERR_NO_FILE){

FileUploadComponent::_uploadedFilesArray() - APP/plugins/file_upload/controllers/components/file_upload.php, line 477
FileUploadComponent::startup() - APP/plugins/file_upload/controllers/components/file_upload.php, line 201
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 88
11/05/2009 8:06 pm

How are you uploading your data?

It looks to me like you forgot to add enctype="multipart/form-data" to your form because the only thing being submitted is the filename, not the actual file -- that only happens when you haven't set enctype="multipart/form-data" in your html form.

You can use the FormHelper to do that:
  1. $form->create('Upload', array('type' => 'file'));


Or you can use plain-jane HTML:
  1. <form action="/uploads/add" method="post" enctype="multipart/form-data">


Hope that helps,
Nick
11/06/2009 4:40 am

that's it

thanks Nick!
working great!
11/06/2009 12:59 pm

Awesome

Glad I could help. =)

Add Comment

Please login or register to submit a comment.