Recieving files with Zend_Form_Element_File
- Posted by thomasw at 01:44:02 // //
- Filter
How to receive a file from Zend_Form_Element_File is often a difficult question.
When you have problems you should read below to get an idea of the handling and to prevent possible problems:
Let’s expect our form has a file element like this one:
$element = new Zend_Form_Element_File('file');
$element->setDestination('/MyDir');
In past, before ZF 1.8, when you wanted to get the uploaded file you had to call receive() afterwards like this…
if ($form->isValid($this->getPost())) {
if (!$element->file->receive()) {
print_r($element->file->getMessages());
}
}
Now many people said, and I think they were right, that it would be a great idea to get the file when calling getValues(). So we added this new feature for ZF 1.8.
This means that that with ZF 1.8 this call is enough:
$values = $form->getValues();
Your file is already transferred… no need to call received afterwards.
But sometime it is wished to call received manually. You could, for example, wish to add a own filter based on a value which you get from your form. So calling getValues() now would mean that you can not add a filter afterwards… as the file is already transferred.
But also for this usecase a solution has been added. You can set a flag to the file element which prevents that the file itself will be received when you call getValues().
Take a look at the following file element:
$element = new Zend_Form_Element_File('file');
$element->setDestination('/MyDir')
->setValueDisabled(true);
Note the added call of setValueDiabled(). It tells the file element that it should not receive the file when you call getValues().
Now you can call getValues() and the file will not be received in the background. But this means, of course, that you have to call receive() manually. Otherwise your file will not be available after the script has been finished.
$values = $form->getValues();
if ($form->isValid($this->getPost())) {
$element->file->addFilter('Rename', false, 'Filename_'.$values['id']);
if (!$element->file->receive()) {
print_r($element->file->getMessages());
}
}
Remember, to have this working you need to call setValueDisabled() otherwise the file is transferred when calling getValues(). When you omit the call then your file will be transferred, due to getValues(), but it will not be renamed, because the rename filter was not available at the time, the file has been received.
Note, that using a filename based on a user input is always a security issue. Use a autoincremented number from your database for example, or be sure that you validate the user input before using it as new filename.
You should also note that I did not use another instance of Zend_File_Transfer…
The file element itself has already a instance available. When you really need to have the instance itself, then use getTransferAdapter() instead of creating a new instance. This is faster, uses less ressources and prevents possible problems with files already being transferred by the other instance.
Greetings
Thomas Weidner
I18N Team Leader, Zend Framework
Zend Framework Advisory Board Member
Zend Certified Engineer for Zend Framework
Add comment
Fill out the form below to add your own comments

Friday, April 24, 2009 - 11:13:35
If running you last code example, calling $element->file->getFileName() after $element->file->receive(),
shouldn’t that return /MyDir/Filename_1? Actually it returns /MyDir/filename_of_uploaded_file
Friday, April 24, 2009 - 13:23:38
getFileName() returns the actual name of the file…
This means, before setting the filter it returns the original name, and after setting the filter it returns the filtered name
Friday, April 24, 2009 - 14:19:48
Nope, it does not (at least not in 1.8 beta1).
In Zend_File_Transfer_Adapter_Http::receive() the filtered $filename is set to $this->_files[$file][’tmp_name’]; while Zend_File_Transfer_Adapter_Abstract::getFileName() looks at $this->_files[$file][’name’] for the filename.
Friday, April 24, 2009 - 15:15:37
receive() receives the file… of course when it does this, the internal name changes… tmp_name is the internal temporary filename… but this has nothing to do with the filename the user gave.
Btw: When you see a problem with ZF code please fill in a issue instead of discussing here single lines of code. A blog is not the proper media to get help on code which is not part of the blog entry.
Friday, April 24, 2009 - 15:22:56
Sure, i was just wondering if theres a method to return the actual path of the transfered file after receive().
Friday, April 24, 2009 - 17:13:25
Ah, you fixed that in trunk…that was fast, thanks :)
Monday, May 4, 2009 - 14:33:49
There is any possibility to automatically process some filters also ? Not just put the file into destination folder….
Monday, May 4, 2009 - 21:42:00
Just read the above blog entry in detail.
As you can see there is a addFilter() method within the file element.
Friday, May 8, 2009 - 23:58:32
Actually i was curious if would be possible to automatically use filters (as rename) automatically, with setValueDisabled not been set…
Monday, May 11, 2009 - 23:04:02
I don’t understand your question.
setValueDisabled is per default set to false. This has nothing to do with filters per se.
Tuesday, May 19, 2009 - 19:08:27
I think there is a mistake in the examples: $form doesn’t have a method getPost()
Saturday, August 1, 2009 - 21:55:32
$element izn`t available.
I use
$element = $form->getElement(’textfile’);
$element->addFilter(’Rename’, array(false, ‘Filename_’.$i.’.txt’));
Saturday, August 1, 2009 - 22:11:04
$element isn`t available.
I use
$element = $form->getElement(’textfile’);
$element->addFilter(’Rename’, array(false, ‘Filename_’.$i.’.txt’));
But it doesn’t work
Tuesday, August 4, 2009 - 10:36:40
I’m sorry. It works.
$element->addFilter(’Rename’, ‘Filename_’.$i.’.txt’);
Tuesday, August 4, 2009 - 11:03:03
@Tomek:
No one said that the form has a isPost() method. You may note the $this and not the $form variable, which implies that the controller and not the form has this method.
@Vladimir:
When you supress the array keys you need to have them in the right order, otherwise you may notice unexpected behaviour.
Tuesday, August 4, 2009 - 15:54:05
thank
I can’t disable file auto uploading if I call $form->getValues(). In file with form i set
$this->getElement(’imagefile’)->setValueDisabled(true);
in controller $form->getElement(’textfile’)->setValueDisabled(true);
$model = new Default_Model_Guestbook($form->getValues());
$id = $model->save();
//get last inserted id
//move files
$element = $form->textfile;
$element->addFilter(’Rename’, ‘file’.$id.’.txt’);
if (!$element->receive()) {
print_r($element->getMessages());exit();
}
file isn’t renamed. If i use before
$form->getElement(’textfile’)->setValueDisabled(true);
// Since we now know the form validated, we can now
// start integrating that data sumitted via the form
// into our model:
//print_r($form->getValues());exit();
$model = new Default_Model_Guestbook($form->getValues());
$id = $model->save();
//get last inserted id
//move files
$element = $form->textfile;
$element->addFilter(’Rename’, ‘file’.$id.’.txt’);
if (!$element->receive()) {
print_r($element->getMessages());exit();
}
$model = new Default_Model_Guestbook($form->getValues());
$id = $model->save();
it works, but i don’t know inserted id
Tuesday, August 4, 2009 - 15:56:55
thank
previous comment is wrong
I can’t disable file auto uploading if I call $form->getValues(). In file with form i set
$this->getElement(’imagefile’)->setValueDisabled(true);
in controller $form->getElement(’textfile’)->setValueDisabled(true);
$model = new Default_Model_Guestbook($form->getValues());
$id = $model->save();
//get last inserted id
//move files
$element = $form->textfile;
$element->addFilter(’Rename’, ‘file’.$id.’.txt’);
if (!$element->receive()) {
print_r($element->getMessages());exit();
}
file isn’t renamed. If i use before
$element = $form->textfile;
$element->addFilter(’Rename’, ‘file’.$id.’.txt’);
if (!$element->receive()) {
print_r($element->getMessages());exit();
}
$model = new Default_Model_Guestbook($form->getValues());
$id = $model->save();
it works, but i don’t know inserted id
Sunday, October 11, 2009 - 10:43:38
Thanks for the post, Thomas.
This post clears up some confusion I have seen on other posts. However, you do not state where the various blocks of code are to be placed. Does some of this code need to be placed in an extension of Zend_Form while the rest of the code needs to be placed in a controller class?
I suspect that just the first code block needs to be in a custom Zend_Form class and the rest is in a controller class.
Sunday, October 11, 2009 - 12:29:13
I did not mention where to place this code because you should already know this when working with Zend_Form and their elements.
Take a look into the manual for Zend_Form to see how and where to place form elements, and where to validate them. There are several ways which could be used. Within your model, within the controller or even directly. It depends on your application.