Входной фильтр для загрузки файлов, основное использование

Теперь я немного больше увлекаюсь этим ZF3. Я мог (с некоторой помощью) реализовать почти все, что хотел. Чтобы погрузиться в новую для меня версию, я разработал тестовый проект.

Некоторые вопросы до сих пор остаются без ответа, и я не нашел полезных объяснений.

Моя новая проблема InputFilterAwareInterface. Пробовал примеры для строк из туториала, пока все ок. Но как всегда на легких темах все найдешь, если идти дальше то все резко обрывается.

Мне нужен Inputfilter для файлов xls и xlsx. Я, конечно, гуглил, читал туториалы, искал в зенд-туториале, потому что у меня была мысль, что где-то должна существовать какая-то полная ссылка, но я не смог ее найти.

Итак, я попробовал это:

    $inputFilter->add([
                'type'     => 'Zend\InputFilter\FileInput',
                'name'     => 'DCL_Path',
                'required' => true,
                'validators' => [
                        ['name'    => 'FileUploadFile'],
                        [
                                'name'    => 'FileMimeType',
                                'options' => [
                                        'mimeType'  => ['text/xls', 'text/xlsx']
                                ]
                        ],
                        [
                                'name'    => 'Filesize',
                                'options' => [
                                        'max' => 4096
                                ]
                        ],
                ],
//              'filters'  => [
//                      [
//                              'name' => 'FileRenameUpload',
//                              'options' => [
//                                      'target'=>'./data/upload',
//                                      'useUploadName'=>true,
//                                      'useUploadExtension'=>true,
//                                      'overwrite'=>true,
//                                      'randomize'=>false
//                              ]
//                      ]
//              ],
        ]); 

Как вы видите, я все еще борюсь с частью валидатора. Какой правильный синтаксис для проверки файлов xls и xlsx с максимальным размером, скажем, 4 МБ?

И после этого, как насчет области фильтра, я сделал следующее в своем действии контроллера только потому, что я привык к

if ($form->isValid()) {
                    $data = $form->getData();
                    // Upload path
                    $location = "public/files/";
                    // A bit validation of uploaded file
                    $allowedExtension = array('xls', 'xlsx');
                    $extension = explode('.', $data['DCL_Path']['name']);
                    $extension = end($extension);
                    //$import['DCL_Path']=$data['DCL_Path']['name'];
                    //$fileName = time() . '.' . $extension;
                    $fileName = $data['DCL_Path']['name'];
                    // Check if everything is OK!
                    //echo $fileName;
                    if (0 === $data['DCL_Path']['error'] && in_array($extension, $allowedExtension)) {
                        move_uploaded_file($data['DCL_Path']['tmp_name'], $location . $fileName);
                    } else {
                        echo 'Something went wrong!';
                    }

Является ли move_uploaded_file($data['DCL_Path']['tmp_name'], $location . $fileName); устаревшим с фильтрами в интерфейсе? И опять же, как в этом случае будет синтаксис?

И одно из моих самых больших пожеланий: знает ли кто-нибудь учебник, в котором ясно объясняются различные возможности и ключи обоих вариантов (валидатора и фильтра)? Иногда не верится, что нужно столько времени, чтобы найти только нужные ключи.

РЕДАКТИРОВАТЬ 1: Показать форму, фильтры и измененный контроллер

вот часть моего класса Form:

<?php
namespace Import\Form;

use Zend\Form\Form;
class ImportForm extends Form
{
    public function __construct($name = null)
    {
        // We will ignore the name provided to the constructor
        parent::__construct('import');

        $this->add([
                'name' => 'DCLID',
                'type' => 'hidden',
        ]);
        $this->add([
                'name' => 'UnitID',
                'type' => 'text',
                'options' => [
                        'label' => 'equipment',

                ],
        ]);
        $this->add([
                'name' => 'DCL_Path',
                'type' => 'File',
                //'required' => true,
                'options' => [
                        'label' => 'path to file',

                ],
                //              'name' => 'FileRenameUpload',
//              'filters' => [
//                      'target'=>'./public/files',
//                      'useUploadName'=>true,
//                      'useUploadExtension'=>true,
//                      'overwrite'=>true,
//                      'randomize'=>false
//                  ],
//              'validators' => [      // Validators.
//                      // Put validator info here.
//              ]
        ]);

здесь часть класса расширена InputFilterAwareInterface

<?php
namespace Import\Model;
use DomainException;
use Zend\Filter\StringTrim;
use Zend\Filter\StripTags;
use Zend\Filter\ToInt;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
use Zend\Validator\StringLength;

class Import implements InputFilterAwareInterface
{
    public $DCLID;
    public $DCL_Path;
    public $Unitname;
    public $UnitID;
    public $Importdate;
    public $Importuser;
    public $Importok;
    public $DCL_Type;
    public $Changed_per_User;
    public $Description_Changes;

    private $inputFilter;

    public function exchangeArray(array $data)
    {
        $this->DCLID= !empty($data['DCLID']) ? $data['DCLID'] : null;
        $this->UnitID= !empty($data['UnitID']) ? $data['UnitID'] : null;
        $this->DCL_Path= !empty($data['DCL_Path']) ? $data['DCL_Path'] : null;
        $this->Importdate= !empty($data['Importdate']) ? $data['Importdate'] : null;
        $this->Importuser= !empty($data['Importuser']) ? $data['Importuser'] : null;
        $this->Importok= !empty($data['Importok']) ? $data['Importok'] : null;
        $this->DCL_Type= !empty($data['DCL_Type']) ? $data['DCL_Type'] : null;
        $this->Changed_per_User= !empty($data['Changed_per_User']) ? $data['Changed_per_User'] : null;
        $this->Description_Changes= !empty($data['Description_Changes']) ? $data['Description_Changes'] : null;
    }

    public function getArrayCopy()
    {
        //      echo var_dump(get_object_vars($this)
        //              );

        return get_object_vars($this);
    }

    public function setInputFilter(InputFilterInterface $inputFilter)
    {
        throw new DomainException(sprintf(
                '%s does not allow injection of an alternate input filter',
                __CLASS__
                ));
    }

    public function getInputFilter()
    {
        if ($this->inputFilter) {
            return $this->inputFilter;
        }

        $inputFilter = new InputFilter();

//      $inputFilter->add([
//              'name' => 'DCLID',
//              'required' => false,
//              'filters' => [
//                      ['name' => ToInt::class],
//              ],
//      ]);
        // Validator für das Upload Element

        $inputFilter->add([
                'type'     => 'Zend\InputFilter\FileInput',
                'name'     => 'DCL_Path',  // Element's name.
                'required' => true,    // Whether the field is required.
                'filters'  => [        // Filters.
                        [
                                'name' => \Zend\Filter\File\RenameUpload::class,
                                'options' => [
                                        'use_upload_extension' => true,
                                        'randomize' => false,
                                        'overwrite' => true,
                                        'target' => 'public/files',
                                ],
                        ],
                ],
                'validators' => [      // Validators.
                        [
                                'name' => \Zend\Validator\File\Extension::class,
                                'options' => [
                                        'extension' => 'xls, xlsx',
                                        'message' => 'File extension not match',
                                ],
                        ],
                        [
                                'name' => \Zend\Validator\File\MimeType::class,
                                'options' => [
                                        'mimeType' => 'text/xls', 'text/xlsx',
                                        'message' => 'File type not match',
                                ],
                        ],
                        [
                                'name' => \Zend\Validator\File\Size::class,
                                'options' => [
                                        'min' => '1kB',  // minimum of 1kB
                                        'max' => '4MB',
                                        'message' => 'File too large',
                                ],
                        ],
                ]
        ]);

и моя часть моего действия контроллера, я думаю, здесь может быть проблема, что-то, вероятно, не логично:

$form = new ImportForm();
        $form->get('submit')->setValue('Add');  //Änderung des LAbels des Submit Buttons, um das Form wiederverwenden zu können
        //echo "hier";
        $request = $this->getRequest();
        if (! $request->isPost()) {     //wurden  Daten über POST geschickt?
            return ['form' => $form];   //Keine Daten, nur Form anzeigen, nicht verarbeiten
        }   
        else {
        //Es wurden Daten gesendet
            //echo "Daten";
            $import = new Import();     //Neue Instanz von Import
            $form->setInputFilter($import->getInputFilter());       //Filter an Form binden
            $form->setData($request->getPost());        //Daten abholen
            //echo $form->isValid();
            if (! $form->isValid()) {
                return ['form' => $form];       //Wenn die Daten nicht valide sind
            }   
            else{           //aus Tableadapter
                    $import->exchangeArray($form->getData());
                    $data = array_merge_recursive(
                            $this->getRequest()->getPost()->toArray(),
                            $this->getRequest()->getFiles()->toArray()
                            );
                    $form->setData($data);
                    if ($form->isValid()) {
                        $data = $form->getData();
                        // Upload path
                //      $location = "public/files/";
//                      $allowedExtension = array('xls', 'xlsx');
//                      $extension = explode('.', $data['DCL_Path']['name']);
//                      $extension = end($extension);
                        $fileName = $data['DCL_Path']['name'];
//                      // Check if everything is OK!
//                      //echo $fileName;
//                      if (0 === $data['DCL_Path']['error'] && in_array($extension, $allowedExtension)) {
//                          move_uploaded_file($data['DCL_Path']['tmp_name'], $location . $fileName);
//                      } else {
//                          echo 'Something went wrong!';
//                      }

                        //-----------------------------------------------------------------
                        // t_dcl befüllen
                        //-----------------------------------------------------------------
                        //$namen = explode(",", $import ); //Konvertierung des Strings in ein Array
                        //echo "<pre>"; var_dump($namen); echo "</pre>"; //Formartierte Ausgabe des Arrays
                        $this->table->saveImport($import);  

EDIT2: опубликуйте часть действия контроллера, чтобы обсудить порядок некоторых операторов:

действие контроллера

$form = new ImportForm();
        $form->get('submit')->setValue('Add');  
        $request = $this->getRequest();
        if (! $request->isPost()) {     
            return ['form' => $form];   
        }   
        else {
            $import = new Import();     //Neue Instanz von Import
            $form->setInputFilter($import->getInputFilter());       
            $form->setData($request->getPost());        
            $data = array_merge_recursive(
                    $this->getRequest()->getPost()->toArray(),
                    $this->getRequest()->getFiles()->toArray()
                    );
            $form->setData($data);
            if (! $form->isValid()) {
                return ['form' => $form];       
            }   
            else{           
                    $import->exchangeArray($form->getData());
                    $data = $form->getData();
                    $fileName = $data['DCL_Path']['name'];

Верна ли позиция $form->setInputFilter($import->getInputFilter());? Или когда мне нужно привязать Inputfilter к форме?

Осталась небольшая проблема: теперь у меня есть сообщение:

Тип файла не соответствует

Я попытался загрузить файл .xlsx


person pia-sophie    schedule 10.07.2017    source источник


Ответы (1)


Пожалуйста, попробуйте это для InputFilter

        $inputFilter->add([
            'type'     => 'Zend\InputFilter\FileInput',
            'name'     => 'DCL_Path',  // Element's name.
            'required' => true,    // Whether the field is required.
            'filters'  => [        // Filters.
                [
                    'name' => \Zend\Filter\File\RenameUpload::class,
                    'options' => [
                        'use_upload_extension' => true,
                        'randomize' => false,
                        'overwrite' => true,
                        'target' => 'public/files',
                    ],
                ],
            ],
            'validators' => [      // Validators.
                [
                    'name' => \Zend\Validator\File\Extension::class,
                    'options' => [
                        'extension' => 'xls, xlsx',
                        'message' => 'File extension not match',
                    ],
                ],
                [
                    'name' => \Zend\Validator\File\MimeType::class,
                    'options' => [
                        'mimeType' => 'text/xls', 'text/xlsx',
                        'message' => 'File type not match',
                    ],
                ],
                [
                    'name' => \Zend\Validator\File\Size::class,
                    'options' => [
                        'max' => '4MB',
                        'message' => 'File too large',
                    ],
                ],
            ]
        ]);

А вот для контроллера

    if($this->getRequest()->isPost()) {
        // merge post and files
        $request = $this->getRequest();
        $data = array_merge_recursive(
            $request->getPost()->toArray(),
            $request->getFiles()->toArray()
        );

        // passing data
        $form->setData($data);

        // execute validator
        if($form->isValid()) {
            // execute file filters.
            $data = $form->getData();
        }
    }

При использовании \Zend\Validator\File\Extension, \Zend\Validator\File\MimeType и \Zend\Validator\File\FileSize вам не нужно вручную проверять контроллер с помощью этого кода.

if (0 === $data['DCL_Path']['error'] && in_array($extension, $allowedExtension)) {}

Поскольку проверка будет выполнена, когда мы вызовем $form->isValid().

А при использовании \Zend\Filter\File\RenameUpload вам больше не нужно использовать move_uploaded_file(). Потому что этот фильтр переместит загруженный файл в папку назначения, которую мы определили в опции 'target' => 'public/files'.

Фильтрация выполняется, когда мы вызываем $form->getData();

А по поводу объяснения Validator и Filter предлагаю вам создать отдельный пост. Используя отдельный вопрос, будет легко искать в поисковике и поможет найти его другому.

person Dolly Aswin    schedule 11.07.2017
comment
Во-первых: ваш пост действительно полезен, я понял, когда выполняется проверка и когда фильтр начинает работать, и что мое предложение правильное, что раньше оно было дублировано. Во-вторых, я получаю ошибку, которую, вероятно, можно быстро исправить: Плагин с именем Zend\Validator\File\FileSize не был найден в менеджере плагинов Zend\Validator\ValidatorPluginManager Должен ли я получить его через композитор? - person pia-sophie; 11.07.2017
comment
Хорошо, должно быть \Zend\Validator\File\FilesSize Но теперь у меня есть дополнительная проблема, я выбрал файл, и после отправки я получаю это сообщение проверки: требуется значение и не может быть пустым - person pia-sophie; 11.07.2017
comment
Извините, используйте \Zend\Validator\File\Size вместо ` Zend\Validator\File\FileSize` - person Dolly Aswin; 11.07.2017
comment
требуется такое же значение ошибки.. должно быть близко к решению - person pia-sophie; 11.07.2017
comment
Пожалуйста, проверьте Form, вы используете DCL_Path для имени input file? - person Dolly Aswin; 11.07.2017
comment
да, это нормально, но я снова отредактирую свой пост, чтобы показать все, возможно, есть что-то, чего я не видел, что такое двойное или что-то еще. - person pia-sophie; 11.07.2017
comment
Ошибка, вызванная тем, что вы вызвали $form->isValid() без слияния POST с FILES. Здесь код $form->setData($request->getPost());. Сначала следует объединить данные $data = array_merge_recursive( $this->getRequest()->getPost()->toArray(), $this->getRequest()->getFiles()->toArray() ); $form->setData($data); - person Dolly Aswin; 11.07.2017
comment
с фактической версией форма недействительна, но я также изменил типы mime на: 'mimeType' => 'vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', теперь я получаю ошибки нет, но метод работает некорректно. $form-›isvalid() возвращает false. - person pia-sophie; 11.07.2017