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

<?php

namespace Test\Form;

use Zend\Form\Form;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
use Zend\InputFilter\InputFilterProviderInterface;

use Zend\Validator\File\Extension;  
use Zend\Validator\File\Size;
use Zend\Validator\File\ImageSize;
use Zend\Validator\File\MimeType;
use Zend\Filter\File\RenameUpload;

class TestForm extends Form  implements InputFilterProviderInterface{
    
    protected $inputFilter; 
    
    public function __construct($name = null) {

        parent::__construct($name?$name:'test');

        //添加一个文本框
        $this->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

<?php

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

echo "<div class='tf'>";
echo '<div>'.$this->form()->openTag($this->tform).'</div>';


//获取文件上传进度必须要使用该view helper,formFileSessionProgress会创建一个id为progress_key的hidden的input记录文件上传进度获取需要的id
//SessionProgress对应formFileSessionProgress,ApcProgress对应formFileApcProgress,UploadProgress对应formFileUploadProgress
echo $this->formFileSessionProgress();

//文本框
echo '<div>'.$this->formRow($this->tform->get('userName')).'</div>';

//文件input
//存在这样的情况:用户第一次提交后,文件上传了并检验通过了,但是文本框检验不过,此时,不需要用户重新再上传一次文件,所以,在此情况下将文件input隐藏起来
echo '<div '.($this->tempFile?'style="display:none"':'').'>'.$this->formRow($this->tform->get('u')).'</div>';
if ($this->tempFile){
    echo '<div>'.$this->tempFile['name'].'</div>';
}else{
    //上传进度显示
    echo '<div><span style="display:block; float:left;">process:</span><span id="proc" style="display:block; margin-left:60px; width:60px; height: 30px; background-color: 

#dddddd;"></span></div>';
}

echo '<div>'.$this->formRow($this->tform->get('send')).'</div>';

echo '<div>'.$this->form()->closeTag().'</div>';
echo "</div>";

echo "<hr />";

?>

<!-- 以下脚本用于定时获取并显示上传进度 -->
<script>
    
var progressInterval;

function getProgress() {
    var ul = '/test/uploadprogress?id='+$("#progress_key").val();//上传进度通过控制器test/uploadprogress获取
    $.ajax({
        type : "GET",
        url : ul,
        dataType : "json",
        success : function(data, textStatus) {
                        if (!data.done) {
                            var value = Math.floor((data.current / data.total) * 100);
                            showProgress(value);
                        } else {
                            showProgress(100);
                            clearInterval(progressInterval);
                        }
                    },
        error : function(r, t, r){
                        
                    }
    });
}

function startProgress() {
    showProgress(0);
    progressInterval = setInterval(getProgress, 400);
}

function showProgress(amount) {
    $('#proc').html(amount+"%");
}
$(document).ready(
    function(){
        $('#test').submit(startProgress);
    }
);
</script>

    最后是控制器:

//Test/Controller/TestController.php

<?php

namespace Test\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\Session\Storage\SessionArrayStorage;
use Zend\ProgressBar\Upload\SessionProgress;
use Zend\View\Model\JsonModel;

use Test\Form\TestForm;

class TestController extends AbstractActionController {

    public function testformAction() {
        $form = new TestForm();
        $inputFilter = $form->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));
    }
}
    








郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。