php - 上传过程中文件上传进度

标签 php zend-framework2

<分区>

我在文件上传进度方面遇到了一些问题。我在 xampp、windows 7 上使用 zend framework 2.2。

表格(SignupForm):

namespace Application\Form;

 use Zend\Form\Form;
 use Zend\Form\Element;

 class SignupForm extends Form
 {  
     public function __construct($name = null)
     {
        $this->add(array(
            'name' => 'username',
            'type' => 'Text',
            'options' => array(
                'label' => 'Username',
                'label_attributes' => array(
                    'class' => 'formlabel',
                ),
            ),
        ));
                      $this->add(array(
            'type' => 'Zend\Form\Element\File',
            'name' => 'fileupload',
            'attributes' => array(
                'id' => 'fileupload',
            ),
            'options' => array(
                'label' => 'Photo',
                'label_attributes' => array(
                    'class' => 'formlabel',
                ),
            ),
        ));
     }
 }

Controller (IndexController):

<?php

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Application\Model\Signup;
use Application\Form\SignupForm;

class IndexController extends AbstractActionController {

    protected $userTable;
    protected $userTablee;

    public function getSignTable($table, $object) {
        if (!$this->$object) {
            $sm = $this->getServiceLocator();
            $this->$object = $sm->get($table);
        }
        return $this->$object;
    }

    public function indexAction() {
        return new ViewModel();
    }

    public function signupAction() {
        $form = new SignupForm();
        $form->get('submi')->setValue('Submit');

        $request = $this->getRequest();
        if ($request->isPost()) {
            $album = new Signup();
            $t = $this->getSignTable('dbAdapter\dbtable=user', 'userTablee');
            $form->setInputFilter($album->getInputFilter($t));
            $data = array_merge_recursive(
                    $this->getRequest()->getPost()->toArray(),
                    $this->getRequest()->getFiles()->toArray()
            );
            $form->setData($data);

            if ($form->isValid()) {
                $album->exchangeArray($form->getData());
                $this->getSignTable('Album\Model\AlbumTable\dbtable=user', 'userTable')->saveUser($album);
//--------------------------------------------------file upload progress--------------------  
// Form is valid, save the form!
            if (!empty($post['isAjax'])) {
                return new JsonModel(array(
                    'status'   => true,
                    'redirect' => $this->url()->fromRoute('upload-form
/success'),
                    'formData' => $album,
                ));
            } else {
                // Fallback for non-JS clients
                return $this->redirect()->toRoute('upload-form
/success');
            }
        } else {
            if (!empty($post['isAjax'])) {
                 // Send back failure information via JSON
                 return new JsonModel(array(
                     'status'     => false,
                     'formErrors' => $form->getMessages(),
                     'formData'   => $form->getData(),
                 ));
            }                
$filter = new \Zend\Filter\File\RenameUpload("./public/photo/" . $album->username);
                $filter->setUseUploadExtension(true);
                $filter->setRandomize(true);
                $filter->filter($data['fileupload']); 
            } 
        }
        return array('form' => $form);
    }

public function uploadProgressAction()
{
    $id = $this->params()->fromQuery('id', null);
    $progress = new \Zend\ProgressBar\Upload\SessionProgress();
    return new \Zend\View\Model\JsonModel($progress->getProgress($id));
}    

}

模型(注册):

namespace Application\Model;
use Zend\Http\PhpEnvironment\Request;

use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
use Zend\Validator;

class Signup implements InputFilterAwareInterface {
    public $username;
    public $fileupload;
    protected $inputFilter;
    public function exchangeArray($data) {
$this->username = (!empty($data['username'])) ? $data['username'] : null;        
$this->fileupload = (!empty($data['fileupload'])) ? $data['fileupload'] : null;
    }

    public function getArrayCopy() {
        return get_object_vars($this);
    }

    public function setInputFilter(InputFilterInterface $inputFilter) {
        throw new \Exception("Not used");
    }

    public function getInputFilter($adapter = null) {
        if (!$this->inputFilter) {
            $inputFilter = new InputFilter();
$inputFilter->add(array(
                'name' => 'fileupload',
                'required' => true,
            ));
            $this->inputFilter = $inputFilter;
        }
        return $this->inputFilter;
    }
}

View (索引):

<?php
$this->plugin('basePath')->setBasePath('/zendtest/public');
$title = 'Signup';
$this->headTitle($title);
?>
<h1><?php echo $this->escapeHtml($title); ?></h1>
<div class="signupform">
    <?php
    $form->prepare();
    $form->setAttribute('action', $this->url('signup', array('action' => 'signup')));
    $form->setAttribute('method', 'post');
    $form->setAttribute('class', 'signform');
    $form->setAttribute('enctype', 'multipart/form-data');
    echo $this->form()->openTag($form);
    $errmsg = $form->getMessages();
    ?>
    <!--  ----------------------------------------username  -->
    <div class="signupformrow">
        <?php
        echo $this->formLabel($form->get('username'));
        echo $this->formInput($form->get('username'));
        if ($errmsg) {
            if (isset($errmsg['username'])) {
                foreach ($errmsg['username'] as $key => $value) {
                    ?>
                    <span class="formerror">
                        <?php
                        if ($key == "isEmpty") {
                            echo"Username required";
                        } else {
                            echo $value;
                        }
                        ?>
                    </span>
                    <?php
                }
            } else {
                ?>
                <span class="formins"><img src="<?php echo $this->basePath('/images/tick.png'); ?>" /></span>
                <?php
            }
        } else {
            ?>
            <span class="formins">(Username must be 5-69 characters and alphanumeric only)</span>
            <?php
        }
        ?>
    </div>
    <!--  ----------------------------------------file   -->
    <?php echo $this->formFileSessionProgress(); ?>
    <div class="signupformrow">
        <?php
        echo $this->formLabel($form->get('fileupload'));
        echo $this->formFile($form->get('fileupload')); 
        if ($errmsg) {
            if (isset($errmsg['fileupload'])) {
                print_r($errmsg['fileupload']);
                foreach ($errmsg['fileupload'] as $key => $value) {
                    ?>
                    <span class="formerror">
                        <?php
                        if ($key == "isEmpty") {
                            echo'Photo required';
                        } else {
                            echo $value;
                        }
                        ?>
                    </span>
                    <?php
                }
            }
        }
        ?>
    </div>
    <!--  ----------------------------------------submit   -->     
    <div class="signupformrow">
        <label class="formlabel"></label>
        <button>Submit</button>
    </div>
    <?php
    echo $this->form()->closeTag();
    ?>
<!-- ---------------------------------------file upload progressbar-------------------------------------- -->
<div id="progress" class="help-block">
    <div class="progress progress-info progress-striped">
        <div class="bar"></div>
    </div>
    <p></p>
</div>

<script src="<?php echo $this->basePath('/js/jquery.min.js'); ?>"></script>
<script src="<?php echo $this->basePath('/js/jquery.form.js'); ?>"></script>
<script>
var progressInterval;

function getProgress() {
    // Poll our controller action with the progress id
    var url = '<?php echo $this->url('signup') ?>/upload-progress?id=' + $('#progress_key').val();
    $.getJSON(url, function(data) {
        if (data.status && !data.status.done) {
            var value = Math.floor((data.status.current / data.status.total) * 100);
            showProgress(value, 'Uploading...');
        } else {
            showProgress(100, 'Complete!');
            clearInterval(progressInterval);
        }
    });
}

function startProgress() {
    showProgress(0, 'Starting upload...');
    progressInterval = setInterval(getProgress, 900);
}

function showProgress(amount, message) {
    $('#progress').show();
    $('#progress .bar').width(amount + '%');
    $('#progress > p').html(message);
    if (amount < 100) {
        $('#progress .progress')
            .addClass('progress-info active')
            .removeClass('progress-success');
    } else {
        $('#progress .progress')
            .removeClass('progress-info active')
            .addClass('progress-success');
    }
}

$(function() {
    // Register a 'submit' event listener on the form to perform the AJAX POST
    $('#signup').on('submit', function(e) {
        e.preventDefault();

        if ($('#fileupload').val() == '') {
            // No files selected, abort
            return;
        }

        // Perform the submit
        //$.fn.ajaxSubmit.debug = true;
        $(this).ajaxSubmit({
            beforeSubmit: function(arr, $form, options) {
                // Notify backend that submit is via ajax
                arr.push({ name: "isAjax", value: "1" });
            },
            success: function (response, statusText, xhr, $form) {
                clearInterval(progressInterval);
                showProgress(100, 'Complete!');

                // TODO: You'll need to do some custom logic here to handle a successful
                // form post, and when the form is invalid with validation errors.
                if (response.status) {
                    // TODO: Do something with a successful form post, like redirect
                    // window.location.replace(response.redirect);
                } else {
                    // Clear the file input, otherwise the same file gets re-uploaded
                    // http://stackoverflow.com/a/1043969
                    var fileInput = $('#fileupload');
                    fileInput.replaceWith( fileInput.val('').clone( true ) );

                    // TODO: Do something with these errors
                    // showErrors(response.formErrors);
                }
            },
            error: function(a, b, c) {
                // NOTE: This callback is *not* called when the form is invalid.
                // It is called when the browser is unable to initiate or complete the ajax submit.
                // You will need to handle validation errors in the 'success' callback.
                console.log(a, b, c);
            }
        });
        // Start the progress polling
        startProgress();
    });
});
</script>
</div>

模块配置:

<?php

return array(
    'router' => array(
        'routes' => array(
            'home' => array(
                'type' => 'Zend\Mvc\Router\Http\Literal',
                'options' => array(
                    'route'    => '/zendtest/',
                    'defaults' => array(
                        'controller' => 'Application\Controller\Index',
                        'action'     => 'index',
                    ),
                ),
            ),
            'application' => array(
                'type'    => 'Literal',
                'options' => array(
                    'route'    => '/zendtest/application',
                    'defaults' => array(
                        '__NAMESPACE__' => 'Application\Controller',
                        'controller'    => 'Index',
                        'action'        => 'index',
                    ),
                ),
                'may_terminate' => true,
                'child_routes' => array(
                    'default' => array(
                        'type'    => 'Segment',
                        'options' => array(
                            'route'    => '/[:controller[/:action]]',
                            'constraints' => array(
                                'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
                                'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',
                            ),
                            'defaults' => array(
                            ),
                        ),
                    ),
                ),
            ),
//===================================signup================================================================
             'signup' => array(
                 'type'    => 'segment',
                 'options' => array(
                     'route'    => '/zendtest/application/signup[/][:action][/:id]',
                     'constraints' => array(
                         'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                         'id'     => '[0-9]+',
                     ),
                     'defaults' => array(
                         'controller' => 'Application\Controller\Index',
                         'action'     => 'signup',
                     ),
                 ),
             ), 
        ),  // routes end
    ), // router ends
    'service_manager' => array(
        'factories' => array(
            'translator' => 'Zend\I18n\Translator\TranslatorServiceFactory',
        ),
    ), 
    'translator' => array(
        'locale' => 'en_US',
        'translation_file_patterns' => array(
            array(
                'type'     => 'gettext',
                'base_dir' => __DIR__ . '/../language',
                'pattern'  => '%s.mo',
            ),
        ),
    ), 
    'controllers' => array(
        'invokables' => array(
            'Application\Controller\Index' => 'Application\Controller\IndexController'
        ),
    ), 
    'view_manager' => array(
        'display_not_found_reason' => true,
        'display_exceptions'       => true,
        'doctype'                  => 'HTML5',
        'not_found_template'       => 'error/404',
        'exception_template'       => 'error/index',
        'template_map' => array(
            'layout/layout'           => __DIR__ . '/../view/layout/layout.phtml',
            'application/index/index' => __DIR__ . '/../view/application/index/index.phtml',
            'application/index/signup' => __DIR__ . '/../view/application/signup/index.phtml',
            'error/404'               => __DIR__ . '/../view/error/404.phtml',
            'error/index'             => __DIR__ . '/../view/error/index.phtml',
        ),
        'template_path_stack' => array(
            __DIR__ . '/../view',
        ),
    ), 
);

我的注册页面在“/zendtest/application/signup/”打开。

当我点击提交按钮时没有任何反应。

更新:

如果我使用以下代码,请告诉我如何使用“Zend\ProgressBar\Upload\UploadProgress”将文件上传进度条添加到我的表单中。我应该如何更改 Controller 、模型或 View ?

Controller :

if ($form->isValid()) {
                $album->exchangeArray($form->getData());
                $album->act_code = Rand::getString(5);
                $album->dkey = Rand::getString(5);
                $this->getSignTable('Album\Model\AlbumTable\dbtable=user', 'userTable')->saveUser($album);
//==================================================file========================================
                $filter = new \Zend\Filter\File\RenameUpload("./public/photo/" . $album->username);
                $filter->setUseUploadExtension(true);
                $filter->setRandomize(true);
                $filter->filter($data['fileupload']);
            }
        }

过滤和验证模型(Signup.php):

    $inputFilter->add(array(
        'name' => 'fileupload',
        'required' => true,
        'validators' => array(
            $fileValidator->attach(new \Zend\Validator\File\UploadFile(array(
                        'messages' => array(
                            \Zend\Validator\File\UploadFile::NO_FILE => 'Photo required',
                        ),
                            )
                    ), true)
        ),
    ));

View :

  <?php echo $this->formFileSessionProgress(); ?>
    <div class="signupformrow">
        <?php
        echo $this->formLabel($form->get('fileupload'));
        echo $this->formFile($form->get('fileupload'));
        if ($errmsg) {
            if (isset($errmsg['fileupload'])) {
                print_r($errmsg['fileupload']);
                foreach ($errmsg['fileupload'] as $key => $value) {
                    ?>
                    <span class="formerror">
                        <?php
                        if ($key == "isEmpty") {
                            echo'Photo required';
                        } else {
                            echo $value;
                        }
                        ?>
                    </span>
                    <?php
                }
            }
        }
        ?>
    </div>

更新 2:

View :

<div class="signupform">
    <?php
    $form->prepare();
    $form->setAttribute('action', $this->url('signup', array('action' => 'signup')));
    $form->setAttribute('method', 'post');
    $form->setAttribute('class', 'signform');
    $form->setAttribute('id', 'signup');
    $form->setAttribute('enctype', 'multipart/form-data');
    echo $this->form()->openTag($form);
    $errmsg = $form->getMessages();
    ?>
    <!--  ----------------------------------------username  -->
    <div class="signupformrow">
        <?php
        echo $this->formLabel($form->get('username'));
        echo $this->formInput($form->get('username'));
        if ($errmsg) {
            if (isset($errmsg['username'])) {
                foreach ($errmsg['username'] as $key => $value) {
                    ?>
                    <span class="formerror">
                        <?php
                        if ($key == "isEmpty") {
                            echo"Username required";
                        } else {
                            echo $value;
                        }
                        ?>
                    </span>
                    <?php
                }
            } else {
                ?>
                <span class="formins"><img src="<?php echo $this->basePath('/images/tick.png'); ?>" /></span>
                <?php
            }
        } else {
            ?>
            <span class="formins">(Username must be 5-69 characters and alphanumeric only)</span>
            <?php
        }
        ?>
    </div>
    <!--  ----------------------------------------file   -->
    <div class="signupformrow">
        <?php
        echo $this->formLabel($form->get('fileupload'));
        ?>
  <div class="filediv">
        <?php
        echo $this->formFile($form->get('fileupload'));
         ?>
        <a onclick="select_file()" class="pure-button upbutton">Choose an Image</a>
        <br />
            <!--image preview-->
            <img id="upimg" name="upimg" src="" style="">
<br />

                </div>
        <?php
        if ($errmsg) {
            if (isset($errmsg['fileupload'])) {
                foreach ($errmsg['fileupload'] as $key => $value) {
                    ?>
                    <span class="formerror">
                        <?php
                        if ($key == "isEmpty") {
                            echo'Photo required';
                        } else {
                            echo $value;
                        }
                        ?>
                    </span>
                    <?php
                }
            }
        }
        ?>
    </div>
    <!--  ----------------------------------------submit   -->     
    <div class="signupformrow">
        <label class="formlabel"></label>
        <?php
        echo $this->formSubmit($form->get('submi'));
        ?>
    </div>
    <?php
    echo $this->form()->closeTag();
    ?>
</div>
<!--progress bar-->
        <div class="progress">
            <div class="barrr"></div>
            <div class="percenttt">0%</div>
        </div>

<script src="<?php echo $this->basePath('/js/jquery.min.js'); ?>"></script>
<script src="<?php echo $this->basePath('/js/jquery.form.min.js'); ?>"></script> 
<script type="text/javascript">

$(document).ready(function() {
    /* variables */
    var preview = $('#upimg');
    var status = $('.status');
    var percent = $('.percenttt');
    var bar = $('.barrr');

    /* only for image preview */
    $("#fileupload").change(function(){
        preview.fadeOut();

        /* html FileRender Api */
        var oFReader = new FileReader();
        oFReader.readAsDataURL(document.getElementById("fileupload").files[0]);

        oFReader.onload = function (oFREvent) {
            preview.attr('src', oFREvent.target.result).fadeIn();
        };
    });

    /* submit form with ajax request */
    $('#signup').ajaxForm({

        /* set data type json */
        dataType:'json',

        /* reset before submitting */
        beforeSend: function() {
            status.fadeOut();
            bar.width('0%');
            percent.html('0%');
        },

        /* progress bar call back*/
        uploadProgress: function(event, position, total, percentComplete) {
            var pVel = percentComplete + '%';
            bar.width(pVel);
            percent.html(pVel);
        },

        /* complete call back */
        complete: function(data) {
            preview.fadeOut(800);
            status.html(data.responseJSON.status).fadeIn();
        }

    });
});    
        function select_file(){
            document.getElementById('fileupload').click();
            return false;
        }
</script>

表单验证模型(Signup.php):

class Signup implements InputFilterAwareInterface {

    public $username;
    public $fileupload;
    protected $inputFilter;
    protected $usernameValidator;
    protected $fileValidator;
    protected $adapter;

    public function exchangeArray($data) {
        $this->username = (!empty($data['username'])) ? $data['username'] : null;
        $this->fileupload = (!empty($data['fileupload'])) ? $data['fileupload'] : null;
    }

    public function getArrayCopy() {
        return get_object_vars($this);
    }

    public function setInputFilter(InputFilterInterface $inputFilter) {
        throw new \Exception("Not used");
    }

    public function getInputFilter($adapter = null) {
        $this->adapter = $adapter;

        if (!$this->inputFilter) {
            $inputFilter = new InputFilter();
            $usernameValidator = new \Zend\Validator\ValidatorChain();
            $fileValidator = new \Zend\Validator\ValidatorChain();

            $inputFilter->add(array(
                'name' => 'username',
                'required' => true,
                'filters' => array(
                    array('name' => 'StripTags'),
                ),
                'validators' => array(
                            $usernameValidator->attach(
                                    new \Zend\Validator\NotEmpty(array()), true)
                            ->attach(new \Zend\Validator\Regex(array(
                                        'pattern' => '/^[a-z]+[a-z0-9_]+$/',
                                        'messages' => array(
                                            \Zend\Validator\Regex::INVALID => 'Username is not valid',
                                            \Zend\Validator\Regex::NOT_MATCH => 'Only small alphabet, digit and underscore are allowed. Username must start with an alphabet',
                                        ),
                                    )), true)
                )
            ));

            $inputFilter->add(array(
                'name' => 'fileupload',
                'required' => true,
                'validators' => array(
                    $fileValidator->attach(new \Zend\Validator\File\UploadFile(array(
                                'messages' => array(
                                    \Zend\Validator\File\UploadFile::NO_FILE => 'Photo required',
                                ),
                                    )
                            ), true)
                ),
            ));

            $this->inputFilter = $inputFilter;
        }
        return $this->inputFilter;
    }

}

它在表单有效时工作,但如果表单有错误(假设“用户名”字段为空)则它不会显示错误消息(应该来自模型“Signup.php”)和进度条即使文件实际上没有上传,仍然显示文件上传进度。

如果我从“index.phtml”中删除以下行并将它们添加到“layout.phtml”的“head”中,那么表单验证有效但文件上传进度条不起作用(表单提交如下正常的 php 形式)。 But the image is shown by the jquery when the image file is selected.

//index.phtml

    <script src="<?php echo $this->basePath('/js/jquery.min.js'); ?>"></script>
    <script src="<?php echo $this->basePath('/js/jquery.form.min.js'); ?>"></script> 

    //layout.phtml

            <!-- Scripts -->
            <?php echo $this->headScript()->prependFile($this->basePath('/js/html5.js'), 'text/javascript', array('conditional' => 'lt IE 9',))
                                          ->prependFile($this->basePath('/js/bootstrap.min.js'))
                                          ->prependFile($this->basePath('/js/jquery.min.js'))
                    ->prependFile($this->basePath('/js/jquery.form.min.js')) ?>
        </head>

enter image description here

最佳答案

更新状态的 JavaScript 在哪里?除非您没有发布某些内容(或者我错过了),否则您实际上错过了一个重要的部分。

您引用的教程中提到了这一点:

There are a few different methods for getting progress information to the browser (long vs. short polling). Here we will use short polling since it is simpler and less taxing on server resources, though keep in mind it is not as responsive as long polling.

When our form is submitted via AJAX, the browser will continuously poll the server for upload progress.

你有三个选择:

1 - 不断刷新请求服务器进度的页面 - 基本上它会返回一个页面,上面写着“上传 10% 完成......”等等,直到提交整个表单,然后你处理。

2 - 更容易在 iFrame 中进行轮询/更新(因此请不断刷新 iFrame)

3 - 使用 javascript 调用(通过 JSON 上传 - 你的 View 返回 JSON 作为对 HTML 的反对,你不需要标题)然后通过 JavaScript 更新屏幕。

因此,您需要将其中一种方法挂接到您的表单中。

警告:

话虽如此,您需要以正确的方式配置服务器。上传可以基于 session 、基于 APC 或上传进度模块。您可能会发现这些都没有安装在服务器上以最终部署。


更好的整体解决方案(可能)。

所以,既然你无论如何都在使用 JS,那么你也可以在现代浏览器(IE9+、Chrome、FF 等,所以它保存在 main 中使用)中使用 JS 中的一个特性。使用 IE8 它就可以正常工作(没有进度指示器)。到目前为止,我发现它是一个更可靠的替代方案(如果您接受 IE8,用户将获得没有进度条的上传功能)。

您在 XHR 对象的上传属性中添加一个事件监听器。随着上传进度不断调用 EventLister。

您可以将一个挂接到每个文件(这就是我在下面所做的,您需要排队并一次处理一两个,然后在完成后提交主表单)或者您可以挂接到整个表单(一个进度条,一个处理程序服务器端 = 更简单,但用户体验不佳)。

为了提供帮助,这里有一个最近项目的片段,但是网络上有一些教程可以提供帮助。这与您所拥有的有所不同,但变化不大,而且部署和控制起来要简单得多。它使用 jQuery,但如果您使用原始 JS,理论(向 xhr 添加事件监听器)是完全相同的。

我知道这是对您当前方法的一种转变 - 但我也使用了您当前的方法并发现这种方法更好。

jQuery 片段/示例

$.ajax({
xhr: function() {
    var xhrobj = $.ajaxSettings.xhr();
    if (xhrobj.upload) {
        xhrobj.upload.addEventListener('progress', function(event) {
            var percent = 0;
            var position = event.loaded || event.position;
            var total = event.total;
            if (event.lengthComputable) {
                percent = Math.ceil(position / total * 100);
            }
            //Set progress
            $('#upload_' + vr_admin.currentlyUploadIndex + ' .imageProgress .imageProgressBar').css({width: percent * 2});
        }, false);
    }
    return xhrobj;
},
url: upload.php',
type: "POST",
contentType:false,
processData: false,
cache: false,
data: {data fields god here},
success: function(response){
    alert ('UPloaded');
}
}

关于php - 上传过程中文件上传进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20519870/

相关文章:

php - 将不同值存储在一列中时对搜索结果进行分组

javascript - 使用 javascript 时如何保护本地 API URL

javascript - 模态布局放在哪里以及如何用动态内容填充它

php - Symfony2 表单给出关于 FormView 的可捕获错误

php - WooCommerce:在订单中保存对产品的更改时 Hook

php - 如何使用php获取大量数据并将其加载到jquery数据表中

php - 具有业力的加权投票系统

validation - ZF2 : allow empty fieldset, 但验证是否至少填写了一个

php - 如何在 Zend Framework 2 中上传文件?

zend-framework2 - zf2 中的 Lucene 搜索