hello All ,
This post will be helpful for all people who are wishing to get some practicle example for using ‘Zend_Form_Element_File’ of Zend framework’s ‘Zend_Form’.
There will 3 steps to implement it:
- Create form with ‘enctype’ set to ‘multipart/form-data’ using Zend_Form
- Create File upload box using Zend_Form_Element_File
- Upload the file on server and get uploaded file’s detail for saving in database
So Let’s explore these steps one by one:
Step 1: Create form with ‘enctype’ set to ‘multipart/form-data’ using Zend_Form
Setting Form ‘enctype’ to ‘mutipart/form-data’ in Zend framework appears difficult if you don’t know about it. In real it is very simple if you ever got a chance to observe setAttrib() function for setting attributes of any element. Lemme give you an example.
(For example, i am creating ‘DocumentForm’ Class that will handle Document uploading Form)
First thing that you’ll need is to set Zend_Form’s ecryption type to ‘multipart/form-data’. This is must for file uploading.
So here it goes ..
class DocumentForm extends Zend_Form
{
public function __construct($options = null)
{
parent::__construct($options);
// setting Form name,Form action and Form Ecryption type
$this->setName('document');
$this->setAction("");
$this->setAttrib('enctype', 'multipart/form-data');
}
}
Above code will create a form named ‘document’ with encryption type ‘multipart/form-data’. Now lets move to next step.
Step2: Create File upload box using Zend_Form_Element_File
You may notice some new code in Bold here:
class DocumentForm extends Zend_Form { public function __construct($options = null) { parent::__construct($options); // setting Form name, Form action and Form Ecryption type $this->setName(’document’); $this->setAction(”"); $this->setAttrib(’enctype’, ‘multipart/form-data’); // creating object for Zend_Form_Element_File $doc_file = new Zend_Form_Element_File(’doc_path’); $doc_file->setLabel(’Document File Path’) ->setRequired(true); // creating object for submit button $submit = new Zend_Form_Element_Submit(’submit’); $submit->setLabel(’Upload File’) ->setAttrib(’id’, ’submitbutton’); // adding elements to form Object $this->addElements(array($doc_file, $submit)); } }
Bold lines in above code will populate a File Element along with a Submit button on Form.
Now user will select the file for uploading and press the Submit button,so here comes our step 3.
Step 3: Upload the file on server and get uploaded file’s detail for saving in database
This is last but most important step of the process that saves the file on server and returns back file upload details. Above Form will be called by some Controller’s Action so here comes my Controller and Action that will show and handle this form.
class DocumentForm extends Zend_Form { function addAction() { $form = new DocumentForm(); $this->view->form = $form; if ($this->_request->isPost()) { $formData = $this->_request->getPost(); if ($form->isValid($formData)) { /* Uploading Document File on Server */ $upload = new Zend_File_Transfer_Adapter_Http(); $upload->setDestination("/uploads/files/"); try { // upload received file(s) $upload->receive(); } catch (Zend_File_Transfer_Exception $e) { $e->getMessage(); } // so, Finally lets See the Data that we received on Form Submit $uploadedData = $form->getValues(); Zend_Debug::dump($uploadedData, 'Form Data:'); // you MUST use following functions for knowing about uploaded file # Returns the file name for 'doc_path' named file element $name = $upload->getFileName('doc_path'); # Returns the size for 'doc_path' named file element # Switches of the SI notation to return plain numbers $upload->setOption(array('useByteString' => false)); $size = $upload->getFileSize('doc_path'); # Returns the mimetype for the 'doc_path' form element $mimeType = $upload->getMimeType('doc_path'); // following lines are just for being sure that we got data print "Name of uploaded file: $name "; print "File Size: $size "; print "File's Mime Type: $mimeType"; // New Code For Zend Framework :: Rename Uploaded File $renameFile = 'newName.jpg'; $fullFilePath = '/images/'.$renameFile; // Rename uploaded file using Zend Framework $filterFileRename = new Zend_Filter_File_Rename(array('target' => $fullFilePath, 'overwrite' => true)); $filterFileRename -> filter($name); exit; } } else { // this line will be called if data was not submited $form->populate($formData); } } }
and thats it!
There are few problems with your code… fix these:
*) Why do you create two identical file adapters ?
There is already an adapter within the file element, so there is no need to create it manually.
This will lead to failures.
*) You are referring to the last bracket as “will be called when no data is submitted”… this is not true as you will get there when the validation fails… for example, when the submitted file is too big.
Greetings
Thomas
hi Thomas,
Thanks for your problem indications,
i have fixed the missing things in my code and it will work fine now (tested),
I pasted this code from my project so few extra things remained in it but now it is fine. I have tried to keep this example very simple while giving complete idea about file upload Zend_Form_Element_File
Great work.
I would like to add one thing….
use
Zend_Debug::dump($_FILES);
in place of
print_r($_FILES);
and check your results.
thanks for your appreciation and suggestion ,
I’ll update it ..
Currently you are not checking if the file has been received.
Note that within the latest release receive() returns ONLY a boolean and no exception.
And you should mention that due to the setRequired(true) line a user MUST upload a file, he is not able to send the form without an attached file what sometimes is recommended.
Thomas, thanks for taking interest for realizing me the missing stuff. I have added the things that you suggested and hopefully this tutorial will be easy to use for some beginner.
About this comment line: ‘Currently you are not checking if the file has been received.‘,
i am depending on this condition in my code “if ($form->isValid($formData))“. As i have kept my file element as Mandatory [due to setRequired(true) ] so i don’t need any special handling here.
What I forgot:
It is not recommendable to use $_FILES plain. If using so, your user could manipulate the data which is sent and you would not notice this.
The values are all checked, corrected and served by the file adapter itself. Additionally you are missing some nice and sometimes necessary additions.
See the manual or my blog:
->getFileName()
->getFileSize()
->getFileInfo()
->getMimeType()
->getHash()
All this methods do not trust the data which is provided by the user.
Thomas, thanks again for your guidance.
I was thinking to keep this example very simple but now i have added usage example for your suggested functions too.
so there shouldn’t be any Security issues …
Hello I created a simple Form and added it an Zend_Form_Element_File, and I wanted to manipulate the form action by the ajaxForm jquery method,
public function getImportForm($render)
{
require_once ‘Zend/Form.php’;
$form = new Zend_Form();
$form->setAttrib(‘id’,’importForm’);
$form->setAttrib(‘enctype’, ‘multipart/form-data’);
$form->setAction( $this->view->baseUrl().’leads/lead/batchimport’);
$element = new Zend_Form_Element_File(‘import’);
$element->setLabel(‘File to upload’);
// ensure only 1 file
//$element->addValidator(‘Count’, false, 1);
// limit to 100K
//$element->addValidator(‘Size’, false, 202400);
$element->setRequired(true);
// only XLS
//$element->addValidator(‘Extension’, false, ‘xls’);
$form->addElement($element, ‘import’);
$form->addElement(‘submit’,’importSubmit’,array(‘label’=>’Import’));
if($render)
return $form->render();
else
return $form;
}
and here is the action I use in the controller
public function batchimportAction()
{
if (! $this->getRequest()->isXmlHttpRequest()) {
$this->getResponse()->setHttpResponseCode(404)->sendHeaders();
return false;
}
else {
$values = $_REQUEST ;
$leadModel = new leadModel();
if (isset($values[‘importSubmit’])) {
$form= new $this->getImportForm(false);
if($form->isValid($_POST))
{
$adapter= new ZeajaxActionnd_File_Transfer_Adapter_Http();
$adapter->setDestination(‘/var/www/CAR/temp’);
}
$this->_helper->json->sendJson(”);
}
}
}
but when I click on it to test it sends me an unexpected end of XML.
Could you help me with that?
I could help if I try to create my own Form Class?
thanks for your time
How do i rename uploaded file??
I m adding filter for renaming .. but its not working.
If any1 can give example that will help me.
Thanks
Prem
@Prem: Though I was intending to keep my example a bit simple but as per your request, i have added the code that Renames an uploaded File in Zend Framework. For your understanding, i am keeping that code in Green color.
Let me know if you need any further help.
Regards
Ahsan Shahzad
Neither getFileSize or getMimeType work for me. Zend displays an error message stating that they are undefined methods. I’ve looked in the manual – they are present, but they are missing from the API.
Any advice?
Thanks.
@ Mark on: Which Zend framework version you are using ? Please let me know.
getFileSize and getMimeType are valid function of Zend framework but you might be using it wrongly. So try to paste your code here.
Thanks
Ahsan Shahzad
@ Mark: I’m having the same issue with the methods
…
$upload = new Zend_File_Transfer_Adapter_Http();
…
$name = $upload->getFileName(‘file’);
$size = $upload->getFileSize(‘file’);
$mimeType = $upload->getMimeType(‘file’);
…
How can I print the result (render) at index.phtml
??
It will be helping for me if you explain your requirement a bit more. I’ll be in wait for your response.
@Mark: Use 1.8pre… this methods where in past only available within the file transfer class, and since 1.8 they are also available within the file form element.
For those who want to upload/ rename multiple files.
Thanks bro, very nice and simple. Oh btw, you forgot an s on setOptions:
………
$upload->setOptions(array(‘useByteString’ => false));
Very good job! Bravo!
But I have a question: where do you place the uploads folder? Under the public directory? Do I have to change it when I upload my site in a real server? Or should I use a function like the getBaseUrl() function? Thanks
thanks …great tutorial
i read it 3 times and get a fantastic results and sure i put athis is wonderful tutorial>> copy of this lesson on my site here
http://www.aldawaghranet.com
Hi,
Thanks for putting this together it really helps!
One thing I noticed is that in step 3 you have an addAction() in your form class. The dunction refers to $this->_request which isn’t available in Zend_Form so I presume this addAction() method belongs in the controller class.
Thanks again for a great article.
V
Sometimes I think that frameworks are meant to make things Simple . I think that doing this in Vanilla PHP would be a lot easier than with all this ZF Mess
Just noticed an error:
In Step#3:
The following code:
‘class DocumentForm extends Zend_Form’
should read something to this effect:
‘class ClassName extends Zend_Controller_Action.
Basically, you should be extending Zend_Controller_Action and NOT Zend_Form
Hello Ahsan Shahzad, I like ur articles of uploading file but in these articles u have not added the functionality to store image in the database. I m new to zend framework application so please if u don’t mine then help me to how to store image in the database and retrive that image from that database and display on the form.
Please i require urgently……..
Regards,
Jignesh
I try to use your exemple but i got this error :
The file ‘xxxxxxxx’ was illegal uploaded, possible attack
On ZF forum Thomas Wiedner says :
two adapters try to access the files which causes a attacker violation. The file element uses it’s own adapter.
So how do you use two differents adapters whithout this kind of errors !
Generally I do not post on blogs, but I would like to say that this post really forced me to do so, Excellent post!
I’m Out! 🙂
Hi
Ur Example is very nice but there is a problem in file rename the function that describe for rename file is not rename the file also it doesn’t display any error i use the code that u write in but this not work in my application..
if any thing that we need add extra then tell me….
my application on local host so i can use file path like this …….
$fullFilePath = APPLICATION_PATH.’/uploads/’.$renameFile;
$filterFileRename = new Zend_Filter_File_Rename(array(‘target’ => $fullFilePath, ‘overwrite’ => true));
image is stored in uploads folder but it can’t be rename..
so pls tell me if any thing wrong
all type of help is apperciate………
for a very strange reason every file mime type returns application/octet-stream with $form->file->getMimeType();
why is this happenning?
Maybe you use flash uploader…. It is bug…. Try standart and you will see that everything is ok. So you must manually identify mimie type
public function checkcpwd($id,$opassword)
{
$id = (int)$id;
$data = array(‘member_id’=>$id, ‘password’=>$opassword);
$row = $this->fetchRow($data,’member_id=’.(int)$id , ‘password=’.$opassword );
}
***********
iam calling this function to fetch the row from the database where the table contains the given id and password…….
its nott working plz help me
public function uploadAction()
{
$up = new Application_Form_Fuldf();
$this->view->form = $up;
$a = $up->getvalues(file1);
if($this->getRequest()->isPost()) {
if($up->isValid($_POST)) {
$adapter = new Zend_File_Transfer_Adapter_Abstract();
$uploadDir = $_SERVER[‘DOCUMENT_ROOT’];
$a = $adapter->setDestination($uploadDir);
}
}
}
/**** this is my code for file upload when ever iam uploading it is uploading to my tmp folder
how to set the destination path to my webserver
thanks in advance
how can we move the files from tmp location to our required destination in zend frame work 1.10
plz give me tdhe solution for this
thanks in advance
Only a observation… I use $form->setEnctype(‘multipart/form-data’); More clean.. 😉
@marcio: enctype is not needed. It’s automatically set by the file element
@jake: use setDestination() or attach a “rename” filter at the file element
@joaquin: Probably no “finfo” and no “mime_magic_type” extension available. Then, for security reasons, it always fall back to application/octet-stream
For all other I may point to the developer of this component: http://www.thomasweidner.com
The official mailing list is also a good place to search for solutions to a problem.
Thanks for your problem indications,
i have fixed the missing things in my code and it will work fine now.
Bulk Rename
this is wonderful tutorial .. i read it nileegy times and get a fantastic results and sure i put a
copy of this lesson on my site here
Hi im trying to set a multiple files upload form.
The form has 3 file elements.
if i upload just 1 image i get an error.
“noFile ‘foto2’ was not uploaded”
How can i solve this?
This is form definition for that element
$this->addElement(‘file’, ‘foto2’);
$fElement = $this->getElement(‘foto2’);
$fElement->setRequired(false);
if i upload just 1 image i get an error.
“noFile ‘foto2′ was not uploaded”
How can i solve this?
Thanks a lot for a easy tutorial of file upload for zf …….
I am getting following error. How can i solve this.
* File ‘orglogo’ exceeds the defined ini size
thanks for the tutorial! =D
i am new to zend framework.
i just want to ask how are you going to re-position the upload button. For instance, place it next to browse button. sorry for this silly question.
thanks.
Why do i get this error:
File exceeds the defined ini size.
Thanks.
I have been examinating out a few of your stories and i can claim nice stuff. I will definitely bookmark your website.
Hello, some modifications;
I needed to use $upload->setDestination(“./uploads/files/”); (with a dot in front of /uploads) and make an uploads folder inside my public folder with write acces (777)
Also when you want to change the filename, it should be;
$fullFilePath = ‘./uploads/files/’.$renameFile;
instead of:
$fullFilePath = ‘/images/’.$renameFile;
Question;
How does it know where to get the file that needs to be uploaded to the server?
What i want is to have 3 file elements on my form.. with one required, so how do i detect if there is a file in one of my elements that needs to be uploaded?
(each to another directory on my server)
I was thinking something like this:
$values = $this->_request->getParams();
if($values[‘firstfileselect’]!=””)
{
upload first file
}
But it doesn’t work 😦
Please some help..
Owh and perhaps you also kow how i get the file select box to only show/select jpg images… so no other files can be uploaded.
Hi, I got my own answers.. 🙂
with 2 or more file elements in the form i do this in my controller:
————————————————
if(isset($_FILES[‘firstfileselect’]) && $_FILES[‘firstfileselect’][‘name’]!=””)
{
$first_file = pathinfo($_FILES[‘firstfileselect’][‘name’]);
//to check if it is an image file
if($file _file[‘extension’]==”jpg” || $file _file[‘extension’]==”JPG”)
{
$upload = new Zend_File_Transfer_Adapter_Http();
$upload->setDestination(“./uploads/firstfilefolder/”);
$files = $upload->getFileInfo();
try
{
$upload->receive($files[‘fullplant’][‘name’]);
}
catch(Zend_File_Transfer_Exception $e)
{
$this->view->transfererror=$e->getMessage();
}
}
else
{
$this->view->error=”file has no jpg extention”;
}
}
if(isset($_FILES[‘secondfileselect’]) && $_FILES[‘secondfileselect’][‘name’]!=””)
{
//same as above but now for the second file, but other destination location.
}
————————————————
My second question about getting the file select box to only show images;
You could use accept=”image/gif, image/jpeg” in your file element, but almost no browser supports this feature, so i put the check on file extension in the code and if it is different, i show an error. (see above code)
Greets..
ok great but what if i am using my custom form rather than using Zend_Form
?
Hello everybody,
I am used following codes in my application, i am getting any error from those codes.
But i can’t find the uploaded file in the directory. so i think file is not transferred.
Please someone help me.
/* Uploading Document File on Server */
$upload = new Zend_File_Transfer_Adapter_Http();
$upload->setDestination(“./uploads/files/”);
try {
// upload received file(s)
//$upload->receive($reportForm->getValue(‘doc_path’));
$upload->receive($reportForm->getValue(‘doc_path’));
} catch (Zend_File_Transfer_Exception $e) {
$e->getMessage();
}
Thanks everybody.
Hello everybody,
I have used following codes in my application, i am not getting any error from those codes.
But i can’t find the uploaded file in the directory. so i think the file is not transferred to that location.
Please someone help me.
/* Uploading Document File on Server */
$upload = new Zend_File_Transfer_Adapter_Http();
$upload->setDestination(“./uploads/files/”);
try {
// upload received file(s)
//$upload->receive($reportForm->getValue(‘doc_path’));
$upload->receive($reportForm->getValue(‘doc_path’));
} catch (Zend_File_Transfer_Exception $e) {
$e->getMessage();
}
Thanks everybody.
i recieve this error [Tue Apr 03 09:19:59 2012] [notice] child pid 3230 exit signal Segmentation fault (11)