ZendFramework2学习笔记 文件上传、文件上传进度

    修改php.ini以适应文件的要求:

//php.ini

file_uploads = On
post_max_size = 600M
upload_max_filesize = 600M
session.upload_progress.enabled = On
session.upload_progress.freq =  "1%"
session.upload_progress.min_freq = "1"

    以上我们限制了文件大小限制在不超过600MB。

    关于文件上传进度的获取方式,zf2提供了三个类:

Zend\Progressbar\Upload\ApcProgress
Zend\ProgressBar\Upload\SessionProgress
Zend\Progressbar\Upload\UploadProgress
    其中SessionProcess要求php5.4以上,本文以SessionProcess为例,其他2个使用方法一样。

    首先创建文件上传的From:

//Test/Form/TestForm.php

add(array(
            'name' => 'userName',
            'type' => 'Text',
            'options' => array(
                'label' => 'name:',                
            ),
            'attributes' => array(
                'size' => 60,
                'maxlength' => 100,
            ),
        ));
        
        //添加文件上传input
        $this->add(array(
            'name' => 'u',
            'type' => 'File',
            'options' => array(
                'label' => 'file:',                
            ),
            'attributes' => array(
                'id' => 'u_e',
            ),
        ));
        
        //提交按钮
        $this->add(array(
            'name' => 'send',
            'type' => 'Submit',
            'attributes' => array(
                'value' => 'ok',
            ),
        )); 
    }
    
    
   public function getInputFilterSpecification() {
       
        //文件上传后保存到临时目录的filter
        $renameUpload = new RenameUpload(array(
                                    "target"    => __DIR__."/../../../../../uploads",
                                    "randomize" => true,
                                    "use_upload_name" => true,
                                ));
        //验证文件扩展名
        $extention = new Extension('png,jpeg,jpg,bmp,gif,mp4');
        //验证文件大小
        $size = new Size(array('min'=>'1kB', 'max'=>'600MB'));
        //验证文件MIME类型
        $mime = new MimeType(array('image/png','image/jpeg','image/jpg','image/bmp','image/gif','video/mp4','enableHeaderCheck' => true));
        
        return array(
            'userName' => array(
                'required' => true,
                'filters'  => array(
                    array('name' => 'StringTrim'),
                    array('name' => 'StringToLower'),
                ),
                'validators' => array(
                    array('name' => 'NotEmpty'),
                    array('name' => 'Alnum'),
                    array(
                        'name'    => 'StringLength',
                        'options' => array(
                            'encoding' => 'UTF-8',
                            'min'      => 3,
                            'max'      => 256,
                        ),
                    ),
                    array(
                        'name'    => 'Db\NoRecordExists',
                        'options' => array(
                            'table' => 'user',
                            'field' => 'name',
                            'adapter' => $this->adapter,
                        ),
                    ),
                ),
            ),
            'u' => array(
                'required' => true,        
                'filters'  => array(
                    $renameUpload,
                ),
                'validators' => array(
                    $extention,
                    $size,
                    //$imgSize,
                    $mime,
                ),
            ), 
        );
    }
}

    然后创建view:

//Test/view/test/test/testform.phtml

tform->setAttribute('action', $this->url('test', array('action' => 'testform')));
$this->tform->setAttribute('method', 'POST');
$this->tform->prepare();

echo "
"; echo '
'.$this->form()->openTag($this->tform).'
'; //获取文件上传进度必须要使用该view helper,formFileSessionProgress会创建一个id为progress_key的hidden的input记录文件上传进度获取需要的id //SessionProgress对应formFileSessionProgress,ApcProgress对应formFileApcProgress,UploadProgress对应formFileUploadProgress echo $this->formFileSessionProgress(); //文本框 echo '
'.$this->formRow($this->tform->get('userName')).'
'; //文件input //存在这样的情况:用户第一次提交后,文件上传了并检验通过了,但是文本框检验不过,此时,不需要用户重新再上传一次文件,所以,在此情况下将文件input隐藏起来 echo '
tempFile?'style="display:none"':'').'>'.$this->formRow($this->tform->get('u')).'
'; if ($this->tempFile){ echo '
'.$this->tempFile['name'].'
'; }else{ //上传进度显示 echo '
process:
'; } echo '
'.$this->formRow($this->tform->get('send')).'
'; echo '
'.$this->form()->closeTag().'
'; echo "
"; echo "
"; ?>

    最后是控制器:

//Test/Controller/TestController.php

getInputFilter();

        $sessionKey = 'uploadedTempFile';
        $sessionStorage = new SessionArrayStorage();//session存储对象,文件上传成功并检验成功后,将信息保存进session,避免用户再次重新上传文件
        $tempFile = null;
        
        if ($sessionStorage->offsetExists($sessionKey)){
            $tempFile = $sessionStorage->offsetGet($sessionKey);
        }
        
        if ($this->getRequest()->isPost()){//用户提交了表单,处理表单数据           
        
            $postData = array_merge_recursive(//文件信息合并到postdata数组
                $this->getRequest()->getPost()->toArray(),
                $this->getRequest()->getFiles()->toArray()
            );
            
            if (isset($tempFile)) {//本次提交不是首次提交,并且session中有用户上传的文件的缓存数据
                if (!empty($postData['u']['name'])){//用户重新上传了文件,则原来缓存的文件要清除
                    $sessionStorage->offsetUnset($sessionKey);
                    $tempFile = null;
                }else{//用户没有上传新文件,所以,检验表单时不检验file元素
                    $inputFilter->get('u')->setRequired(false);
                }
            }
            
            $form->setData($postData);
            if ($form->isValid()) {//表单检验成功
                $data = $form->getData();
                
                if (empty($data['u']) && $tempFile){//用户没有上传新文件,所以,使用session中缓存的文件
                    $data['u'] = $tempFile;
                    
                    $fileName = $data['u']['name'];
                    $fileMIMEType = $data['u']['type'];
                    $tmpFilePathName = $data['u']['tmp_name'];
                    $fileSize = $data['u']['size'];                
                }                
                
                //保存表单
                //.......
                
                //$this->redirect()->toRoute(
                
            } else {//表单元素检验失败
                $data = $form->getData();
                $fileErrors = $form->get('u')->getMessages();
                if (empty($fileErrors) && isset($data['u']['error'])
                    && $data['u']['error'] === UPLOAD_ERR_OK
                ) {
                    $tempFile = $data['u'];
                    $sessionStorage->offsetSet($sessionKey, $tempFile);   
                }
            }
        } else {//不是用户提交的表单,清空session中的缓存数据
            if ($sessionStorage->offsetExists($sessionKey)){
                $sessionStorage->offsetUnset($sessionKey);
            }
            $tempFile = null;
        }

        return array(
            'tform'     => $form,
            'tempFile' => $tempFile,
        );        
     }

    //获取上传进度的action
    public function uploadprogressAction()
    {
        $id = $this->params()->fromQuery('id', null);
        $progress = new SessionProgress();
        return new JsonModel($progress->getProgress($id));
    }
}
    

    由于上传过程使用了session,因此,需要添加session的启动代码,以保证刷新页面的时候不会出现session错误。

    session的参数配置:

// /config/autoload/local.php

return array(
    'session' => array(
        'config' => array(
            'class' => 'Zend\Session\Config\SessionConfig',
            'options' => array(
                'name' => 'zf2ttttt',
            ),
        ),
        'storage' => 'Zend\Session\Storage\SessionArrayStorage',
        'validators' => array(
            'Zend\Session\Validator\RemoteAddr',
            'Zend\Session\Validator\HttpUserAgent',
        ),
    ),
);

    Application启动后调用session_start:

// /module/Application/Module.php

namespace Application;

use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;

use Zend\Session\SessionManager;
use Zend\Session\Container;

class Module
{
    public function onBootstrap(MvcEvent $e)
    {
        $eventManager        = $e->getApplication()->getEventManager();
        $moduleRouteListener = new ModuleRouteListener();
        $moduleRouteListener->attach($eventManager);
        
	//为表单验证对象设置默认的语言翻译器,以便验证码验证不通过时用默认语言提示用户       
       \Zend\Validator\AbstractValidator::setDefaultTranslator($e->getApplication()->getServiceManager()->get('translator'));
       //启动session
       $this->bootstrapSession($e);
    }

    public function bootstrapSession($e){
        $session = $e->getApplication()->getServiceManager()->get('Zend\Session\SessionManager');
        $session->start();        
    }

    //SessionManager工厂
    public function getServiceConfig() {
        return array(
            'factories' => array(
                'Zend\Session\SessionManager' => function ($sm) {
                    $config = $sm->get('config');
                    if (isset($config['session'])){
                        $session = $config['session'];
                        
                        $sessionConfig = null;
                        if (isset($session['config'])){
                            $class = isset($session['config']['class']) ? $session['config']['class'] : 'Zend\Session\Config\SessionConfig';
                            $options = isset($session['config']['options']) ? $session['config']['options'] : array();
                            $sessionConfig = new $class;
                            $sessionConfig->setOptions($options);
                        }
                        
                        $sessionStorage = null;
                        if (isset($session['storage'])){
                            $class = $session['storage'];
                            $sessionStorage = new $class;
                        }
                        
                        $sessionSaveHandler = null;
                        if (isset($session['save_handler'])){
                            $sessionSaveHandler = $sm->get($session['save_handler']);
                        }
                        
                        $sessionManager = new SessionManager($sessionConfig, $sessionStorage, $sessionSaveHandler);
                    } else {
                        $sessionManager = new SessionManager();
                    }
                    Container::setDefaultManager($sessionManager);
                    return $sessionManager;
                },
            ),
        );
    }
}

    另外,貌似zf2.3版本中文件上传validator的消息字符串的中文翻译在语言文件/vendor/ZF2/resources/languages/zh/Zend_Validate.php中不存在,需要自己添加下:

/vendor/ZF2/resources/languages/zh/Zend_Validate.php

return array(

    ......

    "File has an incorrect extension" => "文件扩展名不正确",
    "Maximum allowed size for file is '%max%' but '%size%' detected" => "值“%size%”超过最小值“%max%”",
    "Minimum expected size for file is '%min%' but '%size%' detected" => "值“%size%”超过最小值“%min%”",
    "File has an incorrect mimetype of '%type%'" => "文件mime类型不正确“%type%”",
    "The mimetype could not be detected from the file" => "文件中检测不到mime类型",
    "File is not readable or does not exist" => "文件不可读或者不存在",
    'File was not uploaded' => "没有上传文件"

);


   













你可能感兴趣的:(ZendFramework2)