Tuesday, August 18, 2009

Zend_Form multiple file uploads

This blog I'm starting with this mini tutorial. Recently I have started using Zend Framework as my main PHP framework. Testing it and playing with different components I decided to create something useful. I created simple form where users could upload more than one file, I started googling how to achieve this. Found some nice tutorials but they did not suited for my needs.
After some time of experiments I ended with this code.

In form class i created files fields by adding these lines of code in my class:



//image upload field1
$this->files = new Zend_Form_Element_File('files');
$this->files->setLabel('Select files to upload')
->setMultiFile(3)
->addValidator(new Zend_Validate_File_IsImage)
->addValidator(new Zend_Validate_File_Size('2MB'))
->addValidator('Count', 3);


With method setMultiFile() I added 3 file fields in my form. Next step is to check in controller if is post and if everything is valid. You can do this with standart isValid() form method. Next to get files and rename them in static or even dynamic directory you should not access data with form method getValues, if you do this all your uploaded files would be LOST.

Upload precess is quite simple here is example how you can upload rename files and place them in dynamic directory:


view->form = new Form_NewItem('Submit');
$request = $this->getRequest();

//check if is post data
if ($request->isPost())
{
//get data and check if data is valid
$data = $request->getPost();
if ($form->isValid($data))
{
//get data from submited form
$name = $form->getValue('name');
$text = $form->getValue('title');

//load model where data would be saved
$itemModel = new Model_Db_Item;

$insertData = array
(
'name' => $this->getUserId(),
'text' => $webTitle,
);

//save data and get unique id
$itemId = $itemModel->insert($insertData);

//check if data is saved
if ($itemId)
{
//take transfer from form element
$adapter = $form->files->getTransferAdapter();
//APP_PUBLIC is set to my www public directory
$destination = APP_PUBLIC . '/uploads/'.(int)($itemId/100).'/'.(int)($itemId%100).'/';
//create directory where files would be hold
if (!file_exists($destination))
mkdir($destination, 0777, 1);

$i=0;
//loop uploaded files
foreach ($adapter->getFileInfo() as $info)
{
//rename file how you like and move it to given destination
$fileName = 'original_'.$i.'.jpg';
$adapter->addFilter('Rename', array('target'=>$destination.$fileName, 'overwrite'=>true));

//if something goes wrong print errors in screen
if (!$adapter->receive($info['name']))
{
die(print_r($adapter->getMessages(),1));
}

$i++;
}
}
}
}
}
}


Thats it you can now upload multiple files in dynamic created directories. If you have any questions, do not be shy leave them in comments.

1 comment:

  1. I think you should iterate through $info and add Rename Filter for each file. It didn't work with me until I changed it like this:

    // rename each file
    $new_name = 'new name;
    foreach ($info as $filename)
    {
    $adapter->addFilter('Rename', $new_name, $filename);
    }

    ReplyDelete