In this post I will describe how to upload and store a file in the database. Yes, you read correct, I will describe how to store a file in the database. I know, a lot of people do not recommend storing files in a database due to performance reasons. Of course, this is an important point you have to consider when you design your application. The reasons why I store files often in the database are:
- all data are stored in one place: the database
- it is easier to test
- it is easier to develop as I do not have to keep database and file system in sync
Enough of bla-bla, let us dive in the code. First the table definition for MySQL:
CREATE TABLE my_files ( id INT(11) NOT NULL AUTO_INCREMENT, name VARCHAR(75) NOT NULL, type VARCHAR(255) NOT NULL, size INT(11) NOT NULL, data MEDIUMBLOB NOT NULL, created DATETIME, modified DATETIME, PRIMARY KEY (id) );
Note: Use MEDIUMBLOB or LONGBLOB as data type unless you know for sure that the file size of the uploaded files is never bigger than 64kB.
The model is straight-forward:
// app/models/my_file.php
class MyFile extends AppModel {
var $name = 'MyFile';
}
We omit the controller for the moment and create directly the view:
// app/views/my_files/add.ctp (Cake 1.2)
<?php
echo $form->create('MyFile', array('action' => 'add', 'type' => 'file'));
echo $form->file('File');
echo $form->submit('Upload');
echo $form->end();
?>
// app/views/my_files/add.thtml (Cake 1.1)
<form action="/my_files/add" enctype="multipart/form-data" method="post">
<?php echo $html->file('File'); ?>
<?php echo $html->submit('Upload'); ?>
</form>
So, now we are ready to build the controller and to implement the add() function:
// app/controllers/my_files_controller.php (Cake 1.2)
class MyFilesController extends AppController {
function add() {
if (!empty($this->data) &&
is_uploaded_file($this->data['MyFile']['File']['tmp_name'])) {
$fileData = fread(fopen($this->data['MyFile']['File']['tmp_name'], "r"),
$this->data['MyFile']['File']['size']);
$this->data['MyFile']['name'] = $this->data['MyFile']['File']['name'];
$this->data['MyFile']['type'] = $this->data['MyFile']['File']['type'];
$this->data['MyFile']['size'] = $this->data['MyFile']['File']['size'];
$this->data['MyFile']['data'] = $fileData;
$this->MyFile->save($this->data);
$this->redirect('somecontroller/someaction');
}
}
}
// app/controllers/my_files_controller.php (Cake 1.1)
class MyFilesController extends AppController {
function add() {
if (!empty($this->params['form']) &&
is_uploaded_file($this->params['form']['File']['tmp_name'])) {
$fileData = fread(fopen($this->params['form']['File']['tmp_name'], "r"),
$this->params['form']['File']['size']);
$this->params['form']['File']['data'] = $fileData;
$this->MyFile->save($this->params['form']['File']);
$this->redirect('somecontroller/someaction');
}
}
}
Easy, isn’t it? Up to now we have stored the file in the database. To retrieve the file from the database, we need a download() action which we add to our controller:
function download($id) {
Configure::write('debug', 0);
$file = $this->MyFile->findById($id);
header('Content-type: ' . $file['MyFile']['type']);
header('Content-length: ' . $file['MyFile']['size']); // some people reported problems with this line (see the comments), commenting out this line helped in those cases
header('Content-Disposition: attachment; filename="'.$file['MyFile']['name'].'"');
echo $file['MyFile']['data'];
exit();
}
Well, I know that this action is probably not very cake-like, the proper way would be to use a layout and a view, but this way I have less to write ;-)
So, that’s it. We have finished our very simple upload/download application.
Update (2006-08-05): Fixed a security hole in the code above, see also “Be careful with file uploads”. Thanks to Lamby.
Update (2007-06-09): Fixed a small bug in the download function. Thanks to Wilhelm Raab!
Update (2007-10-15): The name “File” led to problems with the core class with the same name, hence I renamed table name, model name, etc. Thanks to “fyi” for the hint!
Update (2007-12-11): Updated for CakePHP 1.2.
Update (2009-02-20): Adding comment to the header(‘Content-length’) statement in the download method

Pretty interesting! It seems like you are saying it’s best for development and testing. Do you have a method to convert back once that is done? And would you recommend something like this in a live app, like a way to keep people from leeching files by linking directly to them?
No, I don’t do any conversions, i.e. in the live application are the files stored in the database, too. Otherwise it would be useless to test a functionality you do not use in the live application ;-)
A View is there to define the presentation of the data to the user. With a raw bytestream such as a file, there is no ‘presentation’ to be defined…
I am having some difficulties retrieving binairies correctly ( the image gets jibbered or the pdf is corrupt). Text files work perfectly.
I use the exact code as provided! First i open the add page in the browser and upload the file. Then I open the http://……/files/download/1 page manually. (instead of 1 a possible id number of the file)
It doesn’t work on both IE and firefox. My server is a WAMP, latest version on a windows 2003 server.
I suspect the issues to depend on corrupt decoding through the http protocol.
issue resolved;
bug in the add function!
insert addslashes method for direct database insertion….
$fileData = addslashes(fread(fopen($this->params['form']['File']['tmp_name'], “r”),
$this->params['form']['File']['size']));
@Lex Slaghuis: I am glad you could resolve the issue. I think you have to use the “addSlashes” function if you use different encodings. In my application I use UTF-8 everywhere, and I don’t experienced any problems.
Let’s say I wanted to add the field product_id to the files table as a foreign key to the products table. How would this look in function add() {}?
@Shane Shepherd: If the product_id is in the same form as the file upload is you do not have to add anything. Otherwise you have to do something like:
$this->params['form']['File']['product_id'] = $productId;
@cakebaker – Sweet! You rock! Thanks!
Hmm. What would you think would happen if uploaded a form of my own something along the lines of:
Assuming there was a mechanism for obtaining uploaded files, I would then have your mySQL password, something very dangerous on a shared host. Enjoy :)
[input hidden="data[File][tmp_name]” value=”/var/www/cake/app/config/database.php” /]
[input hidden="data[File][size]” value=”9999999″ /]
(It ate my previous post’s HTML tags, so reposting with square brackets. Sorry)
I had trouble with corrupted JPEGs. I turned out that the view file that displays the image upload form was using a layout file with a ‘wrong’ Byte Order Marker, it was set to ‘dos’. Most text editor can change this to ‘unix’. This resolved my corrupted images.
used on: WinXP, WAMP server, Firefox
I’m a newbie in CakePHP. I want to upload Excel files but not to store it in the database, I just want to read them. Can I do this without creating a model? And can a model created without a database table pair?
@MawciKurL: You do not need a model for file uploads.
I am not sure if I understand your second question correctly. But if your question was “is it possible to create a model which doesn’t use a table”, than the answer is yes. You have to add the following snippet to your model:
var $useTable = false;
Just to elaborate on my previous two comments, you are leaving a large security hole open if you do not check the filenames with file_is_uploaded() or similar. Regards, Lamby
@Lamby: I have fixed it in the post.
Great article, just what I am looking for, but I’m having a problem when I try to implement this in my project (complete newbie, sorry!).
I’ve copied into my project and the view add.thtml loads fine, I select a file and press upload but I get an object not found error “The requested URL was not found on this server.”, but I know it is there because it refers to itself! Am I missing something very obvious?
Cheers, JP
@JP: Hm, maybe you have to change the action property in your add.thtml file?
thanks cakebaker for this helpful example. I want to use it as a milestone and build on top of it – ie. adding more inputs in “add.thtml” !?
I am facing problems trying to add an extra text input as such :
input(‘Modelname/fieldname’, array(’size’ => ‘50′))?>
I believe the problem is because the following 2 lines:
$this->params['form']['Site']['data']=$siteData;
$this->Site->save($this->params['form']);
the data that is to be saved is only about the image !!
any idea on how to modify the add() fuinction in the controller so that it accepts extra params from the form in add.thtml??
I know that the question might sounds silly but i am really a newbie :)
Anyway… I solved it with in very odd way. I discovered that I can retrieve post data from my form in my controler in from 2 Arrays. First is params['form'] which is used in the example. Second is params['data']. That was the key of my solution since ‘data’ – which is the image- is overwritten by $this->params[’form’][’Site’][’data’]=$siteData;
So, I decided to do the following: use params['data'] to save extra inputs and params['forms'] to save the image.
here is exactly what I did:
//app/controllers/files_controller.php
function add()
{
//first save all form data except the image using params['data']
if (empty($this->params['data']))
{
$this->render();
}
else
{
if ($this->Site->save($this->data['Site']))
{
$this->redirect(’sites/index’);
}
}
// socnd save the image using params['forms']
// same code in the example
if (!empty($this->params['form']) && is_uploaded_file($this->params['form']['Site']['tmp_name']))
{
$siteData = fread(fopen($this->params['form']['Site']['tmp_name'],”r”),$this->params['form']['Site']['size']);
$this->params['form']['Site']['data']=$siteData;
$this->Site->save($this->params['form']);
$this->Site->save($siteData);
$this->redirect(’sites/index’);
}
}
hope might be useful but still not convinced with it !!?
Any ideas??
@elswidi: Hm, I don’t know why you use two saves:
$this->Site->save($this->params[’form’]);
$this->Site->save($siteData);
With something like:
$this->params['form']['Site']‘otherdata’] = $this->data['Site']['otherdata'];
$this->params[’form’][’Site’][’data’]=$siteData;
$this->Site->save($this->params['form']['Site'];
it should be possible to save all your data with just one save instead of three saves.
Hi im followed your instructions here on this post. and all worked well with my localserver. however, when im downloading the image from my site on a remote server, the image went crappy. im not sure where the problem lies.
if the problem is with my code, then it shouldnt work in my localserver in the firstplace. i doubt if its cakephp’s code because otherwise you would encounter the problem too.
thanks
For all users that encounter the same problem as warren, the solution can be found in http://groups.google.com/group/cake-php/browse_thread/thread/bf5a3c382b69d599/8f1b0453ffd13640
It took me a while to realize that the line added for the security problem had ’ instead of ‘
is_uploaded_file($this->params[’form’][’File’][’tmp_name’]))
should be
is_uploaded_file($this->params['form']['File']['tmp_name']))
@EmheMah: Thanks for the hint, I have fixed it. Sorry for the inconvenience.
I’m confused why people like to upload files to their database. My thinking is it slows down database access time when there are multiple users and it unnecessarily increases the size of your database. Many low cost web hosts out there that offer shared hosting put a restriction on your database size. Fortunately more and more (and many of the intelligent ones) make your database size as large as your account plan’s disk space size so it doesn’t matter. BUT like I said, I feel it slows things down….because rather than accessing files through a simple HTTP request, it has to go through some PHP and then access the database. Of course the answer is security. No one can straight up access your database. Yes, we can htaccess things and protect directories too though.
Anyway, the way I approached file uploads was by automatically generating folders based upon a numbering system…so if it’s post “15″ then the image(s) will go in a directory like, “images/15/” or whatever files.
This would then avoid the entire possibility of being able to see the php file contents. While one may be able to upload the php file (given that they knew the path), they could download or view it all they wanted…it’s in a normal directory on a web server…the data won’t be visible.
I say eliminate problems through simplicity. Of course storing files/images in a directory makes things infinitely easier for other image gallery scripts, etc.
@Tom: Thanks for your comment.
Well, it depends on your project whether it makes sense to store files in the database. And yes, it is slower than accessing the files directly. But unless you develop a high-traffic web application that’s usually not a problem.
Yes, I am for eliminating problems through simplicity. In my case it is by storing files in the database, which allows me to avoid permission or synchronization problems ;-)
[...] In a comment lamby pointed out a possible security hole in the code of my post “File upload with CakePHP”. He is right, if you know the location of app/config/database.php you can retrieve the database settings including the password. [...]
I’m going to build a (hopefully) high traffic site and choose to store images in DB as described above.
The advantage is the possibility of storing privileges and data in one place.
But to prevent the possible issues that speed might be I’m going to implement some caching is the download function and I will add a thumbnail cache too.
That should get the best from both worlds.
Another cool feature is that you can easily prevent deep-linking to files (photos) on your site – if that’s what you want.
@Bjarke Sørensen: Thanks for your comment and good luck with your application!
It’s sure easy but not practical at all (as you mention). Sometimes I think (while reading different cakephp articles) that those develeopers haven’t had any sites or apps with more than 1000 concurrent users or they are just plain rich to throw money on infrastructures (servers, ram etc).
why not let the webserver deliver the static content? That is just the thing what it does best and if you need an ACL you can allways make somekind of passthrough script.
Think of 100 users pressing the link for the 10meg file at the same time and you get a whopping 100×10meg transfer rate from your mysql pipe exhausting the availible bandwith at full speed and only freeing the memory while the transactions are all over and only putting other requests at hold. IMHO it’s not reasonable if compaired just passing the file identifier to apache as URL or to the passthrough script for delivering the file directly from hdd
@Peeter: Well, as I said before, the decision whether to store files in the database depends on the application you develop. There are a lot of sites out there which will never have 1000 concurrent users, and so performance isn’t an issue for them. On the other side there are high-traffic sites where performance is very important and where having files in the database could become a bottleneck. The analysis of the requirements should give you the answer with which sort of application you have to deal, and based on that you can decide.
I think this method, mixed with some caching, could be an optimal solution….
Thanks for the info.
[...] cakebaker » File upload with CakePHP [...]
Does anybody know why I can upload only small files (
@Marcos: Did you check the value of upload_max_filesize in your php.ini?
I’m a newbie..
I wanted to upload and image but not in the database but in a folder in the webroot, could you help me on this? No resizing needed.
thanks.
@pabs: move_uploaded_file (http://php.net/move_uploaded_file) should help you to accomplish what you want.
Great short tutorial cakebaker (although I was searching for something ’bout CakePHP’s file handling functions, so I guess I’ll just have to keep looking).
However, I found an error in Your code. Very simple one, the HTTP header Content-Disposition should have the filename enclosed in “: header(‘Content-Disposition: attachment; filename=”‘.$file['File']['name'] .’”‘);
Cheers, // W. Raab
@Wilhelm: Thanks for pointing me to that bug. I fixed it in the article.
Do you know how to use FileHandlerComponent in CakePHP? I already used it, but i didn’t work.
I wrote this in my view :
url(“/customers/upload”) ?> method=”post”>
and this function in my customers controller :
var $components = array(‘FileHandler’);
function upload()
{
$this->FileHandler->upload(‘userfile’,'files’);
}
but it didn’t work. Can you help me to fix this problem?
Thanks before..
@Bahari: I am sorry, but I don’t know the FileHandlerComponent. But I am sure the author of this component can help you.
I don’t like the way you put the file data directly into the database. I’d personally use move_uploaded_file() and save the file to a new directory from the temp directory. Wouldn’t this make the application so much faster?
@Antonie: Well, as always in programming, every solution has its advantages and disadvantages. It depends on your concrete application whether it makes sense to store the files in the database. E.g. if an upload functionality is used rather seldom, then performance is usually not that important.
I like resize image jpg file. with lib gd.
I would only like guard the archives in a folder and the names of them in the data base. making an image of the normal size and another one being miniature.
thx.
PLs. tell how can we upload a file with a size greater that 2 MB in cakephp which is the default size my php.ini file handles
@Sadjow: Maybe the following article helps you: http://www.bogdan-net.com/archives/24
@Nikhil: Well, if you define 2MB as maximal size for uploaded files in the php.ini you cannot upload files with a greater size with CakePHP. If you want to upload with a greater size you have to change the value in the php.ini.
I’m using this script, and it works like a charm.. almost. When I try to download a file, a whitespace is added at the start of the file before the last echo is called, which makes the file unreadable (if it’s a binary file).
Outputting the data before the headers are defined shows that the header functions are the sinners. If anyone has experienced the same error, I would be glad to hear from you.
@H-man: Hm, I cannot reproduce this issue here. Do you get the same effect with text files?
Great article, as always.
One trick I figured out in collusion with another developer is to calculate a hash (salt+md5 your file contents), and save the resulting hash in the table.
This allows you to check the hash if you want to make sure you only store one copy of the same file, or to check and see if a file actually has been updated by comparing pre-upload hash and current hash.
This ALSO prevents the exploit that lamby discusses and keeps your files from being sequentially read, ie none of this -
http://site.com/files/1
http://site.com/files/2
http://site.com/files/3
…
- because you can set it up to look for the hash instead of the id.
~confuzus
@confuzus: Thanks for this trick, it may be really useful in certain situations.
Hello,
Thanks for the code.I used the code snippet and the data was saved to the database.This is what i did. I uploaded a JPG file and then tried to download the file. When i tried to download it asked for Save to Disk or Open. I saved it and tried to open and it said it Cannot Open. I need to know how to do two things
1. Why this error is coming? I am able to save and download text files properly
2. I donot want this file dialog to open instead render the uploaded image directly in my view as image tag
Thanks
@Kums: 1. Hm, sounds like an encoding problem to me. Does it work if you use some special characters like äöü in your text files?
2. Simply add the url to the controller action to your image tag:
Hope that helps :)
How do I validate a file type?
@Zunayed: You could define a validation rule for the “type” in your File model.
Hope that helps :)
thanks for this tutorial, it was very helpful. The download function works fine, but how do I display this image in a page?
@Jamie: You could define a similar function as the download function without setting the Content-Disposition header. And in your view where you want to display the image you have to use something like (you could also use the Html helper for this purpose):
Hope that helps :)
Just a FYI for anybody using Cake 1.2 (maybe 1.1?) the model File is reserved, so doing any $this->File operations will result in odd behavior. Change all the references to File and Files to something else like SaveFile or StoreFile
@fyi: Thanks for the hint, I modified the article accordingly.
Anybody could elaborate on confuzus’ idea about md5 hashing? I don’t understand how this prevents the exploit lamby was talking about.
Thanks
@Tim: Hm, I don’t see how confuzus’ idea would prevent the exploit. What it prevents is that you no longer can download any file by guessing the respective ID.
Im getting,
Warning (512): Method HtmlHelper::file does not exist.
Using Cake 1.2
Any help?
Warning (512): Method HtmlHelper::file does not exist
Warning (512): Method HtmlHelper::submit does not exist
Cake 1.2. Why do i get these messages?
@kodiew: Those methods have been moved to the FormHelper in Cake 1.2. So you have to add the FormHelper to the $helpers array of your controller, and to use $form instead of $html. But I am not sure whether you have to modify other things in this example to make it work with Cake 1.2. I have to test it myself.
@kodiew:
That’s because there were some changes with version 1.2.
http://api.cakephp.org/1.2/class_form_helper.html#a4df5df8e975a5b2b1f54fbc1eeb846b
Just change
“$html->file” to “form->file”
and
“$html->submit” to “form->end(‘Upload file’)”
in the file “app/views/images/upload.ctp
(Also note the ending .ctp instead of .thtml is new in version 1.2, but .thtml still works)
Then add
var $helpers = array(‘Form’);
to the file app/controllers/images_controller.php
HTH.
Other than that, I am also interested in how to avoid the security issues that lamby talked about. (I am using 10 – 40 MB files.)
Helmut
@Helmut: Thanks for your comment!
Well, the security issue Lamby talked about should be fixed in the example.
Hi, thanks a lot for those. That got rid of the errors. I got this working fine with 1.1. No luck in 1.2 yet!! the form displays and i add a file, when i click upload it just hangs for a second then seems to just refresh the page. Also what will the view/download file be like?
all good! Got it all working sweet! Thanks everyone!!
@kodiew: Cool to hear that :) What was the problem?
I also use the 1.2 pre_beta version and if i try to upload the file i am getting the error as
Invalid argument supplied for foreach() [CORE\cake\dispatcher.php, line 381]
Shall anybody help me to come out from this issue.
I am also using the pre_beta (5875) and am getting the exact same error as Mary.
@mary: have a look at your view, the above form tags no longer seem to work with the pre_beta.
instead use something like this:
create(‘User’,array(‘action’=>’saveUsers’, ‘type’=>’file’));?>
create('User',array('action'=>'saveUsers', 'type'=>'file'));?>@mary, Adam: I adapted the code in the article to make it work with CakePHP 1.2.
Can I get the Cake 1.1.* version, as opposed to the 1.2 version?
@fmic: The article covers both versions.
[...] File upload with CakePHP (although not exactly what I’m looking for) [...]
many thanks for this short and precise introduction.
one question remains though: are the fields ‘type’ and ’size’ in the file array checked and set by cake or do they just get passed through as in ‘regular’ php? because if these were the ‘regular’ fields i could not depend on their value or even existence as these get set by the client’s browser (or not) afaik
i’m afraid they’re the ‘regular’ ones but as you explicitly mentioned them in your v1.2 controller i got a spark of hope that cake might once again have saved me precious time …
@ben: Yes, they are the “regular” fields set by the client’s browser. There is no Cake magic involved in this case.
I was using basically the same method, and it worked for weeks but then suddenly I was getting corrupted JPEGs and TIFFs. After a a frustrating hour it turns out \x0a was being prepended to the files when downloaded – a UNIX newline. This was brought in with a 3rd-party file which ended in ?> and then a newline for good measure.
Moral of the story – watch for output before you echo the binary stuff here – and in general – DON’T put ?> at the end of a .php file when there is nothing else to follow. It serves no purpose and can only cause headaches for others.
just had to get that off my chest :)
Also – I’ve found that MSIE doesn’t always pay attention to the filetype and Content-disposition correctly, especially when docs like PDFs or MSWord are loaded inside of it. The apparent file extension in the URL can be important. You might want to make sure the download link looks something like this in the view you are linking from:
/documents/fetch//
so it looks like /documents/fetch/1290/somefile.pdf
thanks for the article.
@sbeam: Thanks for your comment! I think having the file extension in the URL could also be useful for the user, so that he knows what type of file he downloads.
hi!i want to upload and store an image in app/webroot/img/uploads by cakephp,but “move_uploaded_file” doesn’t work. cakephp show “failed to open stream:No such file or directory…”;
my code is bellow:
function admin_add(){
if(is_uploaded_file($this->data['Edition']['cover']['tmp_name'])){
$destination = ‘/app/webroot/img/uploads/’.$this->data['Edition']['cover']['name'];
move_uploaded_file($this->data['Edition']['cover']['tmp_name'],$destination);
}
…
}
please tell me why and how to overcome this bug; thanks a lots!
@yunhaihuang: Are you sure the path the $destination variable contains is correct? Shouldn’t it be something like “/path_to_my_project/app/webroot/…”?
the $destination variable is right. up to now, i haven’t fixed the bug yet. i need your help!
my purpose is upload an image and store it into /app/webroot/img/uploads.
i need for some detail solution.
@yunhaihuang: Hm, does the following work?
if (is_uploaded_file($this->data[’Edition’][’cover’][’tmp_name’])){ $fileData = fread(fopen($this->data['Edition']['cover']['tmp_name'], "r"), $this->data['Edition']['cover']['size']); echo $fileData; }thanks for your help! i’ve solved the problem. it’s my fault, the $destination isn’t correct as i thought. thanks lots for your help and apologize for my mistakes.
@yunhaihuang: I’m glad to hear you could solve the problem. Bake on!
I wonder how to enable a flash mp3 player to play audio files uploaded this style since adobe flash only supports files.
Ideas anyone?
@Paul: Hm, I don’t know flash, but if it doesn’t allow you to import files from an url, then you probably have bad luck and you have to store the files on the file system.
Hi, thanks for the help, i think its very easy you explain all very good, an d the best you did it for both cakephp 1.1 and 1.2, but i have a question, what’s up with the name of the files, is there is one with the same name of another you want to upload?, i read all the comments, a friend ask you this before, but what you said: I have fixed it in the post. i don’t understand that, can you explain me a little more please, thanks
@Alfredo: Thanks for your comment!
In the first version I didn’t use is_uploaded_file() and just read the file defined by $this->data['MyFile']['File']['tmp_name']. This allowed you to load a file from the server into the database and to retrieve it later. For example: if you knew the path to app/config/database.php, you could retrieve user name and password for the database…
Hope that answers your question!
[...] File Upload mit Cakephp ist sehr gut in diesem Blogeintrag beschrieben. Eine weitere interessante Methode habe ich in der Bakery [...]
Great article! This just what I needed for my an application I am building for a university. Users mostly upload doc files which are small enough.
The best bonus is the dependency for models which means cake will cascade delete when I remove any projects!
@Eddie: I’m glad this article was helpful for you :)
Me again. I was getting annoyed by how long it took to download files, (40 seconds for a small pdf)and realized that my browser was hanging because it expected more information to be coming. I commented out the header…
//header('Content-length: ' . $file['ProjectFile']['size']);and the speed literally jumped.
If anyone is realizing that downloads are much slower than uploads, give it a shot.
@Eddie: Thanks for this tip!
Thanks for this its been a big help. I ran into a problem that in Safari the file input doesn’t show up in the params array. Any ideas on how to make it work? Thanks again.
Found the problem. I didn’t have the enctype set.
@BBigs: I’m glad you could fix your problem :)
Useful notes here, its one of my favourite bookmarks for cake development… straight to point. Thanks for your hard work and time :)
@Sir P: You are welcome!
[...] http://cakebaker.42dh.com/2006/04/15/file-upload-with-cakephp/ [...]
[...] Spent several hours reading pros and cons of storing images in the database vs storing them in the file system. I don’t see a clear cut winner either way, but since I am working on a project in CakePHP, I will follow the steps laid out at File Upload with CakePHP. [...]
[...] article is mostly in response to Daniel Hofstetter’s great article, File Upload with CakePHP which explains how to save uploaded files in their own database table. In his example (I assume for [...]
[...] una carpeta del servidor y guardarlas directamente en la base de datos. Aunque seguí en CakeBaker esta explicación de Daniel Hofstetter, uno de los colaboradores del proyecto CakePHP, al final me inspiré en la [...]
Hi cakebaker very good article, i’m using your code and my display image function is:
But it looks that images are loading a too slow…here’s a page working with this function: http://algarve.property-algarve.co.uk/
Can you help me improving the load speed or this is normal because the images are in the database? Thank you
@Carlos: Yes, having the images in the database is slower, and especially if you have many images the overhead may be too much. Did you compare the load time of having the images in the database vs. having the images in the file system?
Btw: you should set the correct content type for the files in the display() method, otherwise the browsers have problems with displaying the images, see for example http://algarve.property-algarve.co.uk/my_files/display/6877
I found an interesting problem. The script mostly works perfectly for me, but after I download a file and try to click another link in my application, I get a “cannot modify headers — headers already sent” error.
It goes like this: Load add->upload file->upload successful->download file->download successful->load new page->error.
Anybody else run into this?
Well, I really don’t know why, but commenting out the following line seems to have fixed my bug.
// header(‘Content-length: ‘ . $file['ProjectFile']['size']);
This is found in the download function. Someone else commented that it also speeds up their downloads.
@Jon: Thanks for your comments!
I’m glad you could fix your issue in the meantime. I added a hint to the download() method.
Just so everyone is aware, if you use the below code to display more than one image on a view, it will reset Cake’s session.
<img src="/yourcontroller/displayimageaction/12" />Note: This is only true if CakePHP security is set to HIGH. If it is MEDIUM or below, it should work fine. I’m currently trying to make it work with the HIGH security level.
@Jon: Thanks for this hint, I wasn’t aware of this behavior. At the moment I don’t see a solution for how you could prevent the reset of the session…
this example is very simple but powerful!
point out many key points,
help me quickly build my own up/dl model
thanks.
Just found a bug today in IE 7 that isn’t allowing the download function to work well with images. It works fine in other browsers, of course.
Judging by Google results and some testing, it seems to have something to do with the Content-Disposition: attachment header. Anyone else experience this?
@Norland: You are welcome!
@Jon: It seems like you have to set some caching headers, see the following comment: http://ch.php.net/manual/en/function.header.php#88038.
Hope it helps!
Thanks cakebaker. I checked the link you sent me long ago but I missed that post.
@Jon: Good to hear the link was helpful for you!
Hello,
I m new to Cakephp.. I have done Blog tutorial and few other examples. I need to use the controler’s action in my url. But I dont know how to bring up the view file directly.. http://localhost/cakephp/views/my_file/add.ctp?..
Thanks,
Bharani
@Bharani: Thanks for your comment!
Hm, I don’t understand what you try do accomplish… You can’t access view files via an URL, you have to request a controller action and this action then renders the respective view. Have a look at A Typical CakePHP Request to get a feeling of how CakePHP works.
Hope that helps!
Hi.. i have used your code in my application. and it is working fine for file uploads upto 500 kB. i am unable to upload a file of size 1MB or more. i have also tried changing the datatype of field ‘data’ to longblob but it didnt work out. Any help would be highly appreciable. Also i need help how can i store my uploaded files in a folder instead of database.
@Rahul: Hm, did you check “upload_max_filesize” in your php.ini? And if you want to store the file in the file system, you could use something like:
Hope that helps!
Thanx cakebaker for the help. I checked my php.ini file for the “upload_max_filesize” and it shows 128M that is perfectly fine. I am using Xampp server. pls do the needful. moreover i am unable to move my uploaded files to the destination i have used in the code below. any other hint why am i not able to get it through.
@Rahul: Hm, there are two other settings in php.ini which could affect file uploads: post_max_size and memory_limit (see http://ch.php.net/manual/en/ini.core.php#ini.post-max-size).
I think move_uploaded_file() expects a full path (i.e. ‘/path/to/your/project/app/webroot/[..]‘) and not only the path from the project root.
Hope that helps.
Hi Cakebaker… Thanks for your help. I tried your settings that is to be done to the php.ini file, but it didn’t work out as well. So i found a provision to this that i would like to share with you. I have problem with “max_allowed_packet ” in mysql’s my.ini file which was previously set to 1MB. So i modified it according to my needs. Thanks indeed for your help.
@Rahul: Good to hear you could fix your issue :)
This is awesome, thank you for this concise and delicious recipe for success.
Storing things in the database is my employers mandate for security reasons, much appreciate the elegant way you showed us how to do it.
@Ray: You are welcome!
I needed to display the image in the page for another project and it wasn’t immediately apparent to me how to do that, so this is what i ended up doing:
I added this functionin my controller:
I am processing several file types, so thats why i’m not specifying the image type. you could do for the controller function something like
then i created a blank view, display_artifact.ctp
and a binary layout
Then to tie it all together, I just reference my empty view as the img src
i’m sure others did this in a more concise way, so I’m just offering this up as it works for me. the ingredients for this also came from:
http://edivad.wordpress.com/2007/04/17/cakephp-mysql-and-blob/
^ to reference empty view as img src
<img src="http://mydomain.com/cakebox/artifacts/displayArtifact/93">@Ray: Thanks for your addition!
[...] (Esta es una traducción hecha por mí, del documento de Daniel Hofstetter, el articulo original esta aquí) [...]
+1 for a well written and extremely helpful tutorial.
@Jeffrey: You are welcome!
hi all,
i hv uploaded files with mb size and stored them in database…then im retrieving them from database…bt i cant see images in IE…and its working on firefox better…its on local server…
on live server…after submit to disp details,i m getting “webpage has expired”…in IE7 and firefox works better…
can anyone tell me what can i do?
@abcd: Hm, difficult to say what the problem could be. Maybe it helps to set the cache settings described in http://ch.php.net/manual/en/function.header.php#88038.
[...] Filed under: CakePHP Framework — maxkorytko @ 9:26 pm Refer to this blog post: CakePHP file upload Leave a [...]
how to upload image in cake php from URL??
@udhaya: It is very similar to what is shown in the article. When creating the form you have to remove the “file” type and you have to replace the file input field with a “normal” text field. In the controller you then have to work with fread and fopen.
Hope this helps!