Search code examples
phpzend-frameworkfile-uploadzend-file

PHP: How to rename a file uploaded with Zend_Form_Element_File?


Form:

//excerpt
$file = new Zend_Form_Element_File('file');
$file->setLabel('File to upload:')
    ->setRequired(true)
    ->addValidator('NotEmpty')
    ->addValidator('Count', false, 1)
    ->setDestination(APPLICATION_UPLOADS_DIR);
$this->addElement($file);

Controller:

//excerpt
if ($form->isValid($request->getPost()) {
    $newFilename = 'foobar.txt';
    //how should I rename the file?
    //When should I rename the file? Before or after receiving?
    try {
        $form->file->receive();
        echo 'filename: '. $form->file->getFileName();
    }
}

Questions:

  1. When I call $form->file->getFileName() it returns the full path, not just the file name. How can I output just the name of the file?

    //Answer: First, get an array of the parts of the filename:
    $pathparts = pathinfo($form->file->getFileName());
    //then get the part that you want to use
    $originalFilename = $pathparts['basename'];
    
  2. How can I rename the filename to something I want? Can this be done with the Rename filter? I'm already setting the destination in the form, so all I want to do is change the filename. Maybe I shouldn't be setting the destination in the form? Or maybe this can't be done with a filter. Maybe I should be doing this with a PHP function? What should I do?

    //Answer: Use the rename filter:
    $form->file->addFilter('Rename', 'new-file-name-goes-here.txt');
    

Final Solution:

This is what I ended up doing:

public function foobarAction()
{
    //...etc...

    if (!$form->isValid($request->getPost())) {
        $this->view->form = $form;
        return;
    }

    //the following will rename the file (I'm setting the upload dir in the form)
    $originalFilename = pathinfo($form->file->getFileName());
    $newFilename = 'file-' . uniqid() . '.' . $originalFilename['extension'];
    $form->file->addFilter('Rename', $newFilename);

    try {
        $form->file->receive();
        //upload complete!
        $file = new Default_Model_File();
        $file->setDisplayFilename($originalFilename['basename'])
            ->setActualFilename($newFilename)
            ->setMimeType($form->file->getMimeType())
            ->setDescription($form->description->getValue());
        $file->save();
    } catch (Exception $e) {
        //error: file couldn't be received, or saved (one of the two)
    }
}

Solution

  • To answer question 1, to get a filename from a full path, you can use basename, or pathinfo.

    For example (copy-paste from the doc) :

    $path = "/home/httpd/html/index.php";
    $file = basename($path);         // $file is set to "index.php"
    

    Or :

    $path_parts = pathinfo('/www/htdocs/index.html');
    echo $path_parts['dirname'], "\n";
    echo $path_parts['basename'], "\n";
    echo $path_parts['extension'], "\n";
    echo $path_parts['filename'], "\n"; // since PHP 5.2.0
    


    To rename / move the file, I suppose rename would do the trick, even if it's quite not "Zend Framework solution".

    If the file has not been moved by ZF and is still in the temporary directory, you should use move_uploaded_file -- but as you are using setDestination, I suppose the file is no longer in the sytem's temporary directory.