Ajax File Uploading with Cake and jQuery
Here’s how to upload files in CakePHP using jQuery.
First, make sure you download jQuery 1.2.2 or greater plus the jQuery Form plugin. Place them in the
1 | webroot/js |
folder and link them in your layout file:
1 <?=$javascript->link(array('jquery.js','jquery.form.js'));?>
Now, in this example, I have a table named “Stories” in the database. For each Story, I want to make a text upload option available in the add and edit views. What will happen is that the user will upload a plain-text file, then Cake will place the contents of the file into a
1 | <textarea> |
field, allowing the user to easily upload a text file but still be able to edit its contents before saving the Story.
In the
1 | views/stories |
folder, I’ve created the
1 | edit.ctp |
file. You will need to begin the form using the Form helper. Don’t forget to specify the type as
1 | file |
so that the
1 | <form> |
tag contains the necessary
1 | enctype="multipart/form-data" |
attribute for the form submission to work correctly.
1
2
3 <h1>Edit Story</h1>
<?=$form->create('Story',array('name'=>'storyEditForm','id'=>'storyEditForm','type'=>'file'));?>
You can put whatever input fields you want in the form. I’m just going to include here the actual uploading part:
1
2
3
4
5 <div id="storyTextUpload">
<span><?=$form->input('Story.text', array('label'=>'Current Text ','rows'=>'15','cols'=>'75'));?></span>
<span><?=$form->input('upload_text',array('label'=>'Upload Text File ','type'=>'file'));?></span>
<span><?=$form->button('Upload Text',array('onClick'=>'$(\'#storyEditForm\').ajaxSubmit({target: \'#storyTextUpload\',url: \''.$html->url('/stories/text').'\'}); return false;'));?></span>
</div>
For the Ajax part of the upload, I’ll need to tell jQuery where to update the Ajax request. In this case, it’s going to be the
1 | <div> |
tag with
1 | id="storyTextUpload" |
. Notice that the
1 | onClick |
event is written in escaped jQuery Form plugin syntax. It’s essentially saying to submit the form with
1 | id="storyEditForm" |
and make the update target the element with an id of
1 | "storyTextUpload" |
. I’ve linked the Ajax form submission to a controller action I haven’t written yet called “text”.
I can now finish the form with whatever else I want.
1 <?=$form->end('Submit');?>
All I have to do now is create the text action in the Stories controller that will handle the upload and then create a view to be used in the final Ajax returned response.
In the Controller
When the file is chosen and the user clicks the “Upload Text” button, jQuery will submit the whole form to the
1 | text |
action in the stories controller because of the URL parameter I wrote in the onClick event.
So, in the
1 | controllers/stories_controller.php |
file, I need to include the following function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 function text() {
<span>if (!$this->data['Story']['upload_text']) { //check for uploaded file in $this->data</span>
<span><span>$this->set('error','You must select a text (.txt) file before you can upload.');</span></span>
<span><span>$this->render('text','ajax');</span></span>
<span>} else {</span>
<span><span>$file = new File($this->data['Story']['upload_text']['tmp_name']); //the uploaded file sent by jQuery and parsed by Cake</span></span>
<span><span>if ($this->data['Story']['upload_text']['type'] != 'text/plain') {</span></span>
<span><span><span>$this->set('error','You may only upload text (.txt) files.');</span></span></span>
<span><span><span>$this->render('text','ajax');</span></span></span>
<span><span>} else {</span></span></span>
<span><span><span>$data = h($file->read()); //read file contents and pass through htmlspecialchars function</span></span></span>
<span><span><span>$file->close();</span></span></span>
<span><span><span>$this->set('text',$data);</span>
<span><span><span>$this->render('text','ajax');</span></span></span>
<span><span>}</span></span>
<span>}</span>
}
Notice that once the action fetches the file contents, it assigns it to a Cake variable named
1 | $text |
to be used in the
1 | views/stories/text.ctp |
view.
In the View
In the
1 | views/stories/text.ctp |
file, I’ve included the following code:
1
2
3
4
5
6
7
8
9
10
11 <? if (!empty($error)): ?>
<span><?=$form->input('Story.text', array('label'=>'Current Text ','rows'=>'15','cols'=>'75'));?></span>
<span><?=$form->input('Story.upload_text',array('label'=>'Upload Text File ','type'=>'file'));?></span>
<span><?=$form->button('Upload Text',array('onClick'=>'$(\'#storyEditForm\').ajaxSubmit({target: \'#storyTextUpload\',url: \''.$html->url('/stories/text').'\'}); return false;'));?></span>
<span><p><?=$error;?></p></span>
<? else: ?>
<span><?=$form->input('Story.text',array('label'=>'Current Text ','value'=>$text,'rows'=>'15','cols'=>'75'));?></span>
<span><p>Upload successful</p></span>
<span><?=$form->input('Story.upload_text',array('label'=>'Upload Text File ','type'=>'file'));?></span>
<span><?=$form->button('Upload Text',array('onClick'=>'$(\'#storyEditForm\').ajaxSubmit({target: \'#storyTextUpload\',url: \''.$html->url('/stories/text').'\'}); return false;'));?></span>
<? endif; ?>
That’s it… Now this handy set of functions will take a file and upload its contents the plop the contents into a text field which will be saved to the database after the user clicks the Submit button. Of course you will need to create your own edit/add functions but this much will get the file uploaded for you.
A File Transfer Method
Actually getting the data was shown above. But say I wanted to put the file contents not into a form field but do an actual file transfer to the server. This is simple. Instead of putting
1 | $data |
into a Cake variable, I could make a new file somewhere on the server like so:
1
2
3 $file = new File(WWW_ROOT.'/files/'.intval(rand()).'_text_upload.txt');
$file->write($data);
$file->close();
A Note on Ajax Submissions
The reason why I’ve used jQuery here is that it is the only Ajax framework I’ve been able to find that will serialize the form elements and actually send to the server as a post variable the
1 | <input type="file"> |
element. Usually, in PHP, the file is accessible in the
1 | $_FILES |
variable, but thanks to Cake, I can get the content moved over much more easily by making use of
1 | $this->data |
and the File functions, which you have seen me do. To spare you time trying to get this to work in Prototype (the Ajax framework that the Cake Ajax Helper uses), I hope you’ll stick with my example here and use jQuery. Prototype doesn’t serialize file inputs.
Maybe someone could build a jQuery set for the Ajax helper :) Until then, hope this helps.
Comments
CakePHP jQuery を使用した Ajax ファイルアップロード | Sun Limited Mt.
Feb 5th, 2008, 4:12 am
[...] 下記ページを参考にさせていただきました。 “jQueryを使ったAjaxファイルアップロード” フォーラム – CakePHP Users in Japan David Golding Design Blog – [...]
Feb 15th, 2008, 1:31 pm
The CakePHP core is moving to jQuery. I’ll be helping on that effort to convert existing prototype code to jQuery. Then I my plan is to make a jQuery UI ajax framework on top of CakePHP.
Just a heads up.
Apr 13th, 2008, 2:10 am
Just I want, THX
raj
Apr 23rd, 2008, 9:03 am
Hi,
Is this work with cakephp 1.1.18
<Mauricio Morales> blog </…..> » Blog Archive » CakePHP - JQuery - Ajax File Uploading
Oct 31st, 2008, 9:55 pm
[...] Finalmente encontré un post en el blog de David Golding (autor del libro: Beginning CakePHP) donde explica como hacer funcionar esto de una forma muy simple con JQuery. http://www.davidgolding.net/cakephp/ajax-file-uploading-with-cake-and-jquery.html [...]
Bjorn
Nov 24th, 2008, 3:22 pm
Hi,
im trying to use this example but i keep getting that the form is null. Any idea what im doing wrong? Im trying to adapt it for uploading images if that makes a big difference.
Jamie Holcomb
Dec 20th, 2008, 10:23 am
I used this approach following the example in Beginning CakePHP. However, this is not working on my site at this time. Trying to figure out what the problem is I looked at the source code and this is what came up
is this what the source code should look like for the button?
Thanks for any help.
Jamie Holcomb
Dec 20th, 2008, 10:24 am
1 |
Jan 21st, 2009, 12:35 pm
great job sir. but if we use pure PHP & Mysql and jquery it works? cakephp size?
i m trying to upload a text file, read contents of text file, echo to input form and user can edit before send it.
can u make an example?
links for 2009-02-15 « Richard@Home
Feb 15th, 2009, 10:13 pm
[...] David Golding : davidgolding.net (tags: cakephp ajax jquery file upload) [...]
MCJenkins
Feb 27th, 2009, 11:06 am
What is the field in my Stories table supposed to be called for this to work, text?
MCJenkins
Feb 27th, 2009, 11:18 am
Yes, “Text” as a field in my Stories table worked. I just replaced my default (out of habit) field called Content to Text. Very nice how-to! Thanks David!
Musa
Mar 20th, 2009, 2:15 am
I’ve a page where i want to use this with prototype, i couldn’t figure it out. errors generated. would anyone help me.
thnx
manu
May 14th, 2009, 10:35 am
Thanks Dav
Was the only Ajax File Upload that finally worked together with Cake.
Thanks a lot.
Andrew
Jul 21st, 2009, 11:47 am
When I attempt to use this, the button onclick code in the source ends up encoding the single quotes into ' and I can’t figure out why. Because of this, the form won’t do anything onclick. Any ideas?
wina
Aug 4th, 2009, 1:47 am
why i can only upload 1 time?
at the second time and forth the filename always empty, eventhough i already selected file.
any idea?
Nov 24th, 2009, 6:50 pm
I find a new site support upload to 16 mirror (rapidshare, megaupload, mediafire, hotfile, zshare …) by 1 click. Try it at http://nixpi.com/8319
Dan Skolnik
May 3rd, 2010, 10:53 am
Cannot get jquery file upload example from Beginning CakePHP to work. Any help out there? When I click the upload text button nothing happens. Also there is 2 content boxes displayed.
Thanks
Jun 22nd, 2010, 1:00 am
The great file upload plugin for jQuery is here: http://pixelcone.com/jquery/ajax-file-upload-script/
I used it in Media plugin for CakePHP and it works great


straighten » links for 2008-02-04
Feb 4th, 2008, 2:33 pm
[...] David Golding Design Blog – (tags: cakephp jQuery fileupload) | | | Yahoo!ブックマークに登録 | | | [...]