Uploading Files with Zend Framework (using Zend_File_Transfer)

NOTE: ZF 1.8+ brings significant changes to the file upload process. Click here to view

The Zend_File_Transfer_Adapter_Http class makes it easy to provide file upload functionality in your applications. The availability of numerous validators and filters insures security (of course, when used properly!). You can view all available validator definitions/code in the “zend\validate\file” folder.

Note that you should download the latest version (1.8) for the example below to work correctly (when I used ver 1.7 I got an error message that getFileInfo method does not exist).

The class basically interfaces with the $_FILE php superglobal and provides an object oriented interface.

1. Create the html front-end (.phtml file)

Here is my sample .phtml file / View :

<form enctype=”multipart/form-data” action=”/try/index/upload” method=”POST”>
<input type=”hidden” name=”MAX_FILE_SIZE” value=”100000″ />
Choose a file to upload:<br>
<input name=”uploadedfile1″ type=”file” /> <br />
<input name=”uploadedfile2″ type=”file” /> <br />
<input name=”uploadedfile3″ type=”file” /> <br />
<input type=”submit” value=”Upload File” />
</form>

The ‘form enctype’ MUST be set to multipart/form-data in order for file transfers to work. Also note the hidden field MAX_FILE_SIZE. This field is used by PHP to prevent super-huge files from being attached (another security feature).

Next comes the standard <input type=”file”> directives that provide an interface for users to select files for upload. This particular example provides 3 file upload boxes.

2. Code the Controller Action (uploadAction())

The Zend_File_Transfer_Adapter_Http() is an easy to use object for file transfer. After instantiation, various adapters can be added for increased security and functionality.. In our example below, we restrict the size to 10KB and only accept files with extension .txt.

For a detailed explanation about validators, please read the Zend Framework Manual

public function uploadAction()
{
$request = $this->getRequest();
if ($request->isPost())
{
try
{
$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->addValidator(‘Count’,false, array(‘min’=>1, ‘max’=>3))
->addValidator(‘Size’,false,array(‘max’ => 10000))
->addValidator(‘Extension’,false,array(‘extension’ => ‘txt’,’case’ => true));

$adapter->setDestination(“c:\\web\\tempfiles”);

$files = $adapter->getFileInfo();

foreach($files as $fieldname=>$fileinfo)
{
if (($adapter->isUploaded($fileinfo[name]))&& ($adapter->isValid($fileinfo[‘name’])))
{
$adapter->receive($fileinfo[name]);
//then, store links etc in db for retrieval later..
}

}
var_dump($adapter->getMessages());
}
catch (Exception $ex)
{
echo “Exception!\n”;
echo $ex->getMessage();
}
}

The getFileInfo() function returns an array indexed by the html form field name (‘uploadedfile1′,’uploadedfile2′,’uploadedfile3’ in our case). The destination directory has been set to C:\web\tempfiles\. Note that the webserver must have read/write privileges to this folder.

We then iterate over this collection and check if the file has been uploaded (isUploaded()) and then run the isValid() function over it. The isValid() routine checks if the files violate any of the defined validation rules.

The $adapter->getMessages() command returns an array of all validation errors.

You can use ‘Filters’ to change certain file attributes. For example, if you want to assign your own file name (rename) files prior to hosting them on the server:

public function uploadAction()
{
$request = $this->getRequest();
if ($request->isPost())
{
try
{
$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->addValidator(‘Count’,false, array(‘min’=>1, ‘max’=>3))
->addValidator(‘Size’,false,array(‘max’ => 10000))
->addValidator(‘Extension’,false,array(‘extension’ => ‘txt,sql’,’case’ => true));

$adapter->setDestination(“c:\\web\\tempfiles”);

$files = $adapter->getFileInfo();
//print_r($files);

foreach($files as $fieldname=>$fileinfo)
{
if (($adapter->isUploaded($fileinfo[name]))&& ($adapter->isValid($fileinfo[‘name’])))
{
$extension = substr($fileinfo[‘name’], strrpos($fileinfo[‘name’], ‘.’) + 1);
$filename = ‘file_’.date(‘Ymdhs’).’.’.$extension;
$adapter->addFilter(‘Rename’,array(‘target’=>’c:\\web\\tempfiles\\’.$filename,’overwrite’=>true));

$adapter->receive($fileinfo[name]);
//then, store in db..
}

}
var_dump($adapter->getMessages());
}
catch (Exception $ex)
{
echo “Exception!\n”;
echo $ex->getMessage();
}
}
}

The lines in bold above adds a filter to do the rename. So, a file named abc.txt would get renamed into file_200905140345.txt on the server.

Advertisements

7 thoughts on “Uploading Files with Zend Framework (using Zend_File_Transfer)

  1. Hi
    my cogito want to thank you for this site, even though learning zf he was not that sure he existed.

    i have one problem with the file upload i built based on this tutorial: if the file is fine then it is moved to the right directory and i get the right message, but when i get a bad file and expecting errors, nothing happen no messages at all and the file does not upload.

    this is my action, hope you can take a look at it:

    public function uploadAction ()
    {
    $request = $this->getRequest();
    if ($request->isPost()) {
    try {
    $adapter = new Zend_File_Transfer_Adapter_Http();
    $adapter->addValidator(‘Count’, false, array(‘min’ => 1 , ‘max’ => 3));
    $adapter->addValidator(‘Size’, false, array(‘min’ => 400 , ‘max’ => 100000 , ‘bytestring’ => true));
    $adapter->addValidator(‘Extension’, false, array(‘extension’ => ‘jpg,gif’ , ‘case’ => true));
    //$adapter->addValidator(‘ImageSize’,false,array(‘minwidth’ => 10,’minheight’ => 10,’maxwidth’ => 300, ‘maxheight’ => 300));
    $adapter->addValidator(‘NotExists’, false, ‘images/uploads’);
    $adapter->setDestination(“images/uploads”);
    $files = $adapter->getFileInfo();
    foreach ($files as $fieldname => $fileinfo) {
    /* echo ‘

    ';
                        print_r($files);
                        echo '

    ‘;*/
    if (($adapter->isUploaded($fileinfo[‘name’])) && ($adapter->isValid($fileinfo[‘name’]))) {
    $adapter->receive($fileinfo[‘name’]);
    //then, store links etc in db for retrieval later..
    echo “the file/s were uploaded succesfully”;
    }
    }
    // var_dump($adapter->getMessages());
    } catch (Exception $e) {
    echo “the problem was:”;
    echo $e->getMessage();
    }
    }
    }

  2. Hi Ron,

    You can use the $adapter->getErrors() method to display error messages (if any) like so:

    foreach ($files as $fieldname=>$fileinfo)
    {
    if (($adapter->isUploaded($fileinfo[name]))&& ($adapter->isValid($fileinfo[‘name’])))
    {
    $adapter ->receive ($fileinfo[name]);
    }
    }
    print_r($adapter ->getErrors ());

  3. Firstly, thanks for the article. It was a quick and easy help for me, while I was searching how to upload multiple files at once ;o)

    But I’ve encountered a problem when using filters. I don’t know if it was a problem back then when this article was published, but in the current version of ZF I needed to specify the $fieldname for the filter, otherwise all the file uploads except the first one failed.

    $adapter->addFilter(‘Rename’,array(‘target’=>’c:\\web\\tempfiles\\’.$filename,’overwrite’=>true), $fieldname);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s