Как стать автором
Обновить

Загрузка и переименование файлов

Время на прочтение4 мин
Количество просмотров8.2K
Статья написана для тех, кто уже хоть немного знаком с архитектурой Zend Framework. Если кому-нибудь будет интересно — опишу работу с формами более подробно в отдельной статье.

Для загрузки файлов на сервер с помощью форм в Zend Framework Form есть элемент Zend_Form_Element_File. У него есть фильтр «Rename», который позволяет переименовать закачаный файл. Но есть минус — мы не можем просто указать новое имя для файла, чтобы сохранилось его расширение. Как это сделать? А как быть, если мы используем setMultiFile?



Например, у нас есть следующая форма

class Form_Myform extends Zend_Form
{
  public function __construct($options = null)
  {
    parent::__construct($options);

    $this->setAttrib('enctype', 'multipart/form-data');

    $image = new Zend_Form_Element_File('image');
    $image->setLabel('Image:')
      ->addValidator('Size', false, 1024000)
      ->addValidator('Extension', false, 'jpg,png,gif');

    $submit = new Zend_Form_Element_Submit('go');
    $submit->setLabel('Submit');

    $elements = array($image, $submit);
    $this->addElements($elements);
}


* This source code was highlighted with Source Code Highlighter.


addValidator('Size', false, 1024000) — устанавливаем максимальный размер (1000kB)

addValidator('Extension', false, 'jpg,png,gif') — указываем допустимые расширения

Мы специально не указываем setDestination, потому что будем использовать фильтр Rename.

Итак, форма у нас есть, теперь будет принимать файл. Лезем в контроллер и пишем следующее

$request = $this->getRequest();
$form = new Form_Myform();
if ($request->isPost()) {
  if ( $form->isValid( $request->getPost() ) ) {
    $file = $form->image->getFileInfo();
    $ext = split("[/\\.]", $file['image']['name']);
    $newName = 'newname.'.$ext[count($ext)-1];

    $form->image->addFilter('Rename', realpath(dirname('.')).
          DIRECTORY_SEPARATOR.
          'upload'.
          DIRECTORY_SEPARATOR.
          $newName);

    $form->image->receive();
  }
}


* This source code was highlighted with Source Code Highlighter.


$file = $form->image->getFileInfo() — берём информацию о закачанном файле image

$ext = split("[/\\.]", $file['image']['name']) — вырезаем расширение из имени файла

$newName = 'newname.'.$ext — задаём новое имя со старым расширением (имя можно сгенерировать, при желании, случайным образом)

$form->image->addFilter('Rename' ... — добавляем фильтр «Rename» к элементу формы image, где передаём новое имя + полный путь к файлу на сервере

$form->image->receive() — переносим файл в нашу папку из временной. Фильтр применяется автоматически

Также у Zend_Form_Element_File есть метод setMultiFile(), который даёт возможность отправить сразу несколько файлов в одном элементе формы. Например:

$image = new Zend_Form_Element_File('image');
    $image->setLabel('Image:')
      ->addValidator('Size', false, 1024000)
      ->addValidator('Extension', false, 'jpg,png,gif')
      ->setMultiFile(3);


* This source code was highlighted with Source Code Highlighter.


В данном случае все фильтры и валидаторы будут относиться ко всем файлам сразу. Можно даже указывать минимальное и максимальное количество файлов, которые будут загружаться, с помощью валидатора «Count»

->addValidator('Count', false, array('min' => 1, 'max' => 3))


Но есть одно большое «НО». Фильтр «Rename» переименует все файлы «в один». Как быть в такой ситуации? Выход есть. Идём опять в контроллер:

$request = $this->getRequest();
$form = new Form_Myform();
if ($request->isPost()) {
  if ( $form->isValid( $request->getPost() ) ) {
    $adapter = $form->image->getTransferAdapter();
    $i = 0;
    foreach ($adapter->getFileInfo() as $file) {
      $ext = split("[/\\.]", $file['name']);
      $newName = 'newname'.$i.'.'.$ext[count($ext)-1];
      $adapter->addFilter('Rename', realpath(dirname('.')).
          DIRECTORY_SEPARATOR.
          'upload'.
          DIRECTORY_SEPARATOR.
          $newName);
      $adapter->receive($file['name']);
      $i++;
    }
  }
}


* This source code was highlighted with Source Code Highlighter.


В данном случае мы используем напрямую File_Transfer_Adapter и его метод receive(). Но забудте тогда про валидатор «Count», т.к. он будет считать неверное количество файлов. Так же ошибки выводятся только для одного файла, даже если они были у всех.

Советую, если можно обойтись без setMultiFile(), то лучше его не используйте. Создайте лучше несколько элементов формы File и всё будет работать отлично.
Теги:
Хабы:
+7
Комментарии12

Публикации

Изменить настройки темы

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн