Search code examples
phpzend-frameworkfile-uploadmultifile-uploader

multi picture upload in zend framework, how to?


i have an issue with uploading multiple files to disk. here is my code.

i have a request with 2 pictures that gets sent to a upload function. the 2 pictures are in a var called $multiUpload

$folderPath = '/var/www/';
if (is_array($multiUpload)){
            $file = array();
            $filename = array();

            foreach($multiUpload as $key=>$val){
                // get the file extension
                $file[] = explode('.',$val);

                // create custom file name
                $filename[] = time().'.'.$file[$key][1];

                //send to the upload function
                $this->uploadToDisk($folderPath, $filename[$key]);

                // sleep 1 sec so that the pic names will be different
                sleep(1);
            }
                 return $filename;

        }


public function uploadToDisk($folderPath, $filename)
{

    $adapter = new Zend_File_Transfer_Adapter_Http();
    $adapter->setDestination($folderPath);
    $adapter->addFilter( 'Rename',array(
            'target' => $folderPath."/".$filename,
            'overwrite' => true
            ) );
    if ($adapter->receive()) {
        $message = "success";
    } else {
        $message = "fail";
    }

    return $message;
}

this will return

Array
(
    [0] => Array
        (
            [0] => 1332977938.jpg
            [1] => 1332977939.jpg
        )

)

but only array[0][0] or 1332977938.jpg will actually get saves to the disk.

Why are they now both get saved? wired

any ideas?


Solution

  • I suspect the second call to uploadToDisk is returning fail because you can only call Zend_File_Transfer_Adapter_Http::receive() once for each file. Since you are not specifying a file when calling receive, it is receiving all of the files the first time you call uploadToDisk and subsequently is failing with a File Upload Attack error.

    Here is some code you can try. This tries to receive each file individually and then save them one at a time with each call to uploadToDisk.

    A few notes about the code:

    • The first parameter to uploadToDisk ($val) may need to be changed as I am not sure what the original values are. It should correspond to one of the element names used for the file upload (See Zend_File_Transfer_Adapter_Http::getFileInfo()) for a list of the files.
    • I changed the method for generating a unique filename so you don't have to sleep(1)
    • Zend_File_Transfer_Adapter_Abstract::setDestination() is deprecated and will go away in the future. Instead, just use the Rename filter. When using Rename, setDestination() has no effect.

    And here it is...

    <?php
    
    $folderPath = '/var/www/';
    
    if (is_array($multiUpload)){
        $filenames = array();
    
        foreach($multiUpload as $key => $val){
            // get the file extension
            $ext = explode('.', $val);
            $ext = $ext[sizeof($ext) - 1];
    
            // create custom file name
            do {
                $filename = uniqid(time()) . '.' . $ext;
                $diskPath = $folderPath . $filename;
            } while (file_exists($diskPath));
    
            $filenames[$key] = $filename;
    
            //send to the upload function
            // $val is the file to receive, $diskPath is where it will be moved to
            $this->uploadToDisk($val, $diskPath);
        }
    
        return $filename;
    }
    
    
    public function uploadToDisk($file, $filename)
    {
        // create the transfer adapter
        // note that setDestination is deprecated, instead use the Rename filter
        $adapter = new Zend_File_Transfer_Adapter_Http();
        $adapter->addFilter('Rename', array(
                'target'    => $filename,
                'overwrite' => true
        ));
    
        // try to receive one file
        if ($adapter->receive($file)) {
            $message = "success";
        } else {
            $message = "fail";
        }
    
        return $message;
    }