Zend Framework і фільтр для задання файлові унікального імені

Renames file assigning it a unique nameВ процесі роботи над створенням FOSS двигунця для портфоліо (на основі Zend Framework) в мене виникла потреба задавати завантажуванним на сервер файлам унікальні імена. Для цього я створив фільтр на зразок Zend_Filter_File_Rename, який генерує унікальне ім’я файлу і перейменовує початковий файл.

Код фільтру і приклад його використання ви знайдете одразу під катом.

Фільтр App_Filter_File_SetUniqueName

<?php
// App/Filter/File/SetUniqueName.php
 
/** @see Zend/Filter/Interface.php */
require_once 'Zend/Filter/Interface.php';
 
/**
 * Renames file assigning it a unique name
 *
 * @category   App
 * @package    App_Filter
 * @author     Stepan Tanasiychuk (http://stfalcon.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class App_Filter_File_SetUniqueName implements Zend_Filter_Interface
{
    /**
     * Filter Options
     * @var array
     */
    private $_options;
 
    /**
     * Constructor
     *
     * @param array|string|Zend_Config $options     Options
     * @return void
     */
    public function __construct($options)
    {
        if ($options instanceof Zend_Config) {
            $options = $options->toArray();
        } elseif (is_string($options)) {
            $options = array(
                'targetDir' => $options,
                'nameLength' => 10
            );
        } elseif (!is_array($options)) {
            require_once 'Zend/Filter/Exception.php';
            throw new Zend_Filter_Exception('Invalid options argument provided to filter');
        }
 
        $this->_options = $options;
    }
 
    /**
     * Filter
     * 
     * @param  string $fileSource   Full path to the source file
     * @return string   The path to a new file
     */
    public function filter($fileSource)
    {
        if (! file_exists($fileSource)) {
            return $fileSource;
        }
 
        $pathInfo = pathinfo($fileSource);
        if (isset($this->_options['targetDir'])) {
            $targetDir = $this->_options['targetDir'];
        } else {
            $targetDir = $pathInfo['dirname'];
        }
 
        // Until generated unique name
        while(true) {
            $fileName = self::_randStr($this->_options['nameLength']) 
                        . '.' . $pathInfo['extension'];
            $fileTarget = $targetDir . DIRECTORY_SEPARATOR . $fileName;
            if (! file_exists($fileTarget)) {
                break;
            }
        }
 
        $result = rename($fileSource, $fileTarget);
 
        if ($result === true) {
            return $fileTarget;
        }
 
        require_once 'Zend/Filter/Exception.php';
        throw new Zend_Filter_Exception(sprintf("File '%s' could not be 
                                        renamed. An error occured while 
                                        processing the file.", $fileSource));
    }
 
 
    /**
     * Generates a random string of that length
     * 
     * @param integer $length
     * @return string
     */
    private static function _randStr($length = 10)
    {
        $chars = array('a','b','c','d','e','f',
                       'g','h','i','j','k','l',
                       'm','n','o','p','r','s',
                       't','u','v','x','y','z',
                       'A','B','C','D','E','F',
                       'G','H','I','J','K','L',
                       'M','N','O','P','R','S',
                       'T','U','V','X','Y','Z',
                       '1','2','3','4','5','6',
                       '7','8','9','0');
 
        $name = '';
 
        for($i = 0; $i < $length; $i++) {
            $index = rand(0, count($chars) - 1);
            $name .= $chars[$index];
        }
 
        return $name;
    }
}

Приклад використання

$uploadFile = new Zend_Form_Element_File('uploadFile');
$uploadFile->setLabel('Upload image')
           ->setDestination($this->_tmp)
           ->addValidator('Count', false, 1)
           // limit to 1Mb
           ->addValidator('Size', false, 1048576)
           // only JPEG, PNG, and GIFs
           ->addValidator('Extension', false, 'jpg,png,gif');
$filterOptions = array('targetDir' => $this->_upload,
                       'nameLength' => 10);
$uploadFile->addFilter(new App_Filter_File_SetUniqueName($filterOptions));

Спочатку картинка завантажується в тимчасовий каталог, потім фільтр генерує для неї унікальне ім’я і переміщує її в каталог призначення.

Ніби все. Буду вдячний за доречні зауваження.

4 thoughts on “Zend Framework і фільтр для задання файлові унікального імені

      • Посмотри пример использования ниже.
        In 5.2.2:
        $file=tempnam(‘tmpdownload’, ‘Ergebnis_’.date(Y.m.d).’_’).’.pdf’;
        echo $file;
        tmpdownload/Ergebnis_20071004_xTfKzz.pdf

        • Я дивився. Правда, в мене результат виглядає трохи по іншому – “C:\WINDOWS\Temp\Erg29.tmp.pdf”.
          Унікальне ім’я створюється для .tmp файлу. Якщо після цього додати до нього свое розширення, то можна затерти існуючий файл. Розумієш?

Leave a Reply

Your email address will not be published. Required fields are marked *