如何在Zend Framework 2中进行文件上传?

7

我一直在研究ZF2中的文件上传。

我知道你们很多人会认为这是一个太模糊的问题,但是创建具有更多处理功能的表单元素的最佳方法是什么呢?

我似乎无法确定从哪里开始。我排除了在控制器中处理它,因为这将违反DRY原则。表单对象似乎没有地方可以“钩入”任何代码。视图助手只是用于视图,因此在其中执行任何操作都没有意义。那么只剩下输入过滤器了。但这似乎也不对。

我被引导使用传输适配器,但代码看起来不太像ZF2。

很抱歉这是一个模糊的问题,希望得到同情的回应。学习一个几乎没有文档记录的框架并且我的zend framework 1知识也有些薄弱,进展有些缓慢。

一旦我有一个好的示例工作,我可能会找到一些地方发布它。

5个回答

9
很简单:
[在您的控制器中]
$request = $this->getRequest();
if($request->isPost()) { 
     $files =  $request->getFiles()->toArray();
     $httpadapter = new \Zend\File\Transfer\Adapter\Http(); 
     $filesize  = new \Zend\Validator\File\Size(array('min' => 1000 )); //1KB  
     $extension = new \Zend\Validator\File\Extension(array('extension' => array('txt')));
     $httpadapter->setValidators(array($filesize, $extension), $files['file']['name']);
     if($httpadapter->isValid()) {
         $httpadapter->setDestination('uploads/');
         if($httpadapter->receive($files['file']['name'])) {
             $newfile = $httpadapter->getFileName(); 
         }
     }
} 

更新:我找到了更好的使用文件验证与表单验证的方法:
将以下类添加到您的模块中,例如:Application/Validators/File/Image.php

<?php
namespace Application\Validators\File;

use Application\Validator\FileValidatorInterface;
use Zend\Validator\File\Extension;
use Zend\File\Transfer\Adapter\Http;
use Zend\Validator\File\FilesSize;
use Zend\Filter\File\Rename;
use Zend\Validator\File\MimeType;
use Zend\Validator\AbstractValidator;

class Image extends AbstractValidator
{  
    const FILE_EXTENSION_ERROR  = 'invalidFileExtention';
    const FILE_NAME_ERROR       = 'invalidFileName'; 
    const FILE_INVALID          = 'invalidFile'; 
    const FALSE_EXTENSION       = 'fileExtensionFalse';
    const NOT_FOUND             = 'fileExtensionNotFound';
    const TOO_BIG               = 'fileFilesSizeTooBig';
    const TOO_SMALL             = 'fileFilesSizeTooSmall';
    const NOT_READABLE          = 'fileFilesSizeNotReadable';


    public $minSize = 64;  //KB
    public $maxSize = 1024; //KB
    public $overwrite = true;
    public $newFileName = null;
    public $uploadPath = './data/';
    public $extensions = array('jpg', 'png', 'gif', 'jpeg');
    public $mimeTypes = array(
                    'image/gif',
                    'image/jpg',
                    'image/png',
            );

    protected $messageTemplates = array(   
            self::FILE_EXTENSION_ERROR  => "File extension is not correct", 
            self::FILE_NAME_ERROR       => "File name is not correct",  
            self::FILE_INVALID          => "File is not valid", 
            self::FALSE_EXTENSION       => "File has an incorrect extension",
            self::NOT_FOUND             => "File is not readable or does not exist", 
            self::TOO_BIG               => "All files in sum should have a maximum size of '%max%' but '%size%' were detected",
            self::TOO_SMALL             => "All files in sum should have a minimum size of '%min%' but '%size%' were detected",
            self::NOT_READABLE          => "One or more files can not be read", 
    );

    protected $fileAdapter;

    protected $validators;

    protected $filters;

    public function __construct($options)
    {
        $this->fileAdapter = new Http();  
        parent::__construct($options);
    }

    public function isValid($fileInput)
    {   
        $options = $this->getOptions(); 
        $extensions = $this->extensions;
        $minSize    = $this->minSize; 
        $maxSize    = $this->maxSize; 
        $newFileName = $this->newFileName;
        $uploadPath = $this->uploadPath;
        $overwrite = $this->overwrite;
        if (array_key_exists('extensions', $options)) {
            $extensions = $options['extensions'];
        } 
        if (array_key_exists('minSize', $options)) {
            $minSize = $options['minSize'];
        }  
        if (array_key_exists('maxSize', $options)) {
            $maxSize = $options['maxSize'];
        } 
        if (array_key_exists('newFileName', $options)) {
            $newFileName = $options['newFileName'];
        } 
        if (array_key_exists('uploadPath', $options)) {
            $uploadPath = $options['uploadPath'];
        } 
        if (array_key_exists('overwrite', $options)) {
            $overwrite = $options['overwrite'];
        }    
        $fileName   = $fileInput['name']; 
        $fileSizeOptions = null;
        if ($minSize) {
            $fileSizeOptions['min'] = $minSize*1024 ;
        }
        if ($maxSize) {
            $fileSizeOptions['max'] = $maxSize*1024 ;
        }
        if ($fileSizeOptions) {
            $this->validators[] = new FilesSize($fileSizeOptions); 
        }
        $this->validators[] = new Extension(array('extension' => $extensions));
        if (! preg_match('/^[a-z0-9-_]+[a-z0-9-_\.]+$/i', $fileName)) {
            $this->error(self::FILE_NAME_ERROR);
            return false; 
        }

        $extension = pathinfo($fileName, PATHINFO_EXTENSION); 
        if (! in_array($extension, $extensions)) {
            $this->error(self::FILE_EXTENSION_ERROR);
            return false; 
        }
        if ($newFileName) {
            $destination = $newFileName.".$extension";
            if (! preg_match('/^[a-z0-9-_]+[a-z0-9-_\.]+$/i', $destination)) {
                $this->error(self::FILE_NAME_ERROR);
                return false;  
            }
        } else {
            $destination = $fileName;
        } 
        $renameOptions['target'] = $uploadPath.$destination;
        $renameOptions['overwrite'] = $overwrite;
        $this->filters[] = new Rename($renameOptions); 
        $this->fileAdapter->setFilters($this->filters);
        $this->fileAdapter->setValidators($this->validators); 
        if ($this->fileAdapter->isValid()) { 
            $this->fileAdapter->receive();
            return true;
        } else {   
            $messages = $this->fileAdapter->getMessages(); 
            if ($messages) {
                $this->setMessages($messages);
                foreach ($messages as $key => $value) { 
                    $this->error($key);
                }
            } else {
                $this->error(self::FILE_INVALID);
            }
            return false;
        }
    } 

}

在表单中使用并添加filterInput:

    array(
        'name' => 'file',
        'required' => true,
        'validators' => array(
            array(
                'name' => '\Application\Validators\File\Image',
                'options' => array(
                        'minSize' => '64',
                        'maxSize' => '1024',
                        'newFileName' => 'newFileName2',
                        'uploadPath' => './data/'
                )
            )
        )
    )

在你的控制器中:

    $postData = array_merge_recursive((array)$request->getPost(), (array)$request->getFiles());
    $sampleForm->setData($postData);  
    if ($sampleForm->isValid()) { 
        //File will be upload, when isValid returns true;
    } else {
        var_dump($sampleForm->getMessages());
    }

尊敬的专家,我应该如何在您的示例中设置"required false"的验证? - karim_fci
如果 $files 是空的,您可以使用 IF ELSE 忽略文件验证。 - M Rostami

4

2

从我在IRC(#Zftalk.2)上问到/看到的情况来看,文件组件尚未进行重构。


0

要检索 $_FILES,在控制器中执行以下操作:

$request= $this->getRequest();

    if($request->isPost()){
        $post= array_merge_recursive($request->getPost()->toArray(), $request->getFiles()->toArray());
        print_r($post);
    }

这篇文章有点旧,但我希望它能帮助到某些人。


-1

这些链接都无法帮助到提问者,因为它们没有涉及文件上传。 - Sam
1
现在已经支持了。支持将在ZF2.1中添加。 - michaelbn
@iroybot,这篇文章很旧了!链接已经失效,而且你应该去检查一下最新的ZF2中上传工作的方式。如果你必须使用ZF2 < 2.1,那么请使用$_FILES。 - michaelbn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接