Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I do File uploading in Zend Framework 2?

I have been looking into file uploading in ZF2.

I understand that many of you will think that this is too vague a question, but what is the best way to create form elements which have a bit more processing?

I can't seem to work out where to start. I have ruled out processing it in the controller as this will break DRY principles. The form object doesn't seem to have a place to 'hook' any code into. The view helper is just that, for the view so it doesn't make sense to do anything in that. So that leaves the input filter. That doesn't seem right either.

I have been steered towards transfer adapters but the code looks like it's not very ZF2.

I'm sorry that this is such a vague question and I'm hoping it falls on sympathetic ears. It's hard learning a framework that has very little documentation and compounded with the fact that my zend framework 1 knowledge is a little thin it, progress is a little slow.

Once I have a good example working I will perhaps find some place to post it.

like image 549
thomas-peter Avatar asked Jul 30 '12 09:07

thomas-peter


People also ask

How does PHP file upload work?

Initially files are uploaded into a temporary directory and then relocated to a target destination by a PHP script. The user opens the page containing a HTML form featuring a text files, a browse button and a submit button. The user clicks the browse button and selects a file to upload from the local PC.


3 Answers

it's simple:
[In Your Controller]

$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(); 
         }
     }
} 

UPDATE : I found better way to use file validation with form validation :
Add this class to your module e.g : 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;
        }
    } 

}

Use in form and add filterInput :

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

And in your controller :

    $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());
    }
like image 174
M Rostami Avatar answered Oct 06 '22 04:10

M Rostami


This is a old question, but in case someone else get here, I found this good article:

Create Simple Upload Form with File Validation

This is a good start to work with files in ZF2. ;)

like image 39
Vinicius Garcia Avatar answered Oct 06 '22 04:10

Vinicius Garcia


From what i asked / seen in irc (#Zftalk.2) the file component is yet to be refactored

like image 45
Antoine Hedgecock Avatar answered Oct 06 '22 06:10

Antoine Hedgecock