В процесі роботи над створенням 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)); |
Спочатку картинка завантажується в тимчасовий каталог, потім фільтр генерує для неї унікальне ім’я і переміщує її в каталог призначення.
Ніби все. Буду вдячний за доречні зауваження.
Хм. А почему не использовать http://ua2.php.net/tempnam и переименовывать в реально уникальное название файла ?
Вона для .tmp файлів. Мені ж потрібні оригінальні розширення файлів.
Посмотри пример использования ниже.
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 файлу. Якщо після цього додати до нього свое розширення, то можна затерти існуючий файл. Розумієш?