File uploading with Zend


In a current project I am working on I have a client that requested to have a single page allowing them to update six existing PDF files. The files uploaded are not guaranteed to have the same file name currently on the server, and they will not always be updating every file at the same time.

I encountered the following problem, the form would only validate if all files were selected. I could not get the the form filter to stop running the validators even though those fields were not required. I have some snippets of the code to help elaberate what I am talking about, and I am assume you have some experience working in Zend Framework 2 (ZF2)

BrochureForm:

  $element = new Element\File('brochure_pdf');
  $element
    ->setLabel("Brochure:")
    ->setLabelAttributes(array(
      'class' => 'col-sm-3'
    ))
    ->setAttributes(array(
      'id' => 'brochure_pdf',
      'accept' => 'application/pdf',
  ));
  $this->add($element);

The form is limiting the uploads to PDF files only, notice the attribute on line 9 ‘accept’ => ‘application/pdf’. This will visually filter out files from the window browswer – it doesn’t prevent them from selecting other file types.

BrocureFilter

  $this->add(array(
    'name' => 'brochure_pdf',
    'type' => '\Zend\InputFilter\FileInput',
    'required' 	=> false,
    'filters' 	=> array(
      array('name' => 'StripTags'),
      array('name' => 'StringTrim'),
      array('name' => 'Null'),
      array(
        'name' => 'filerenameupload',
        'options' => array(
          'use_upload_extension' => true,
          'target' => './data/temp/new_brochure',
          'randomize' => true,
        ),
      ),
    ),
    'validators' => array(
      array(
        'name' => '\Zend\Validator\File\Extension',
        'options' => array(
          'extension' => 'pdf',
          'messages' => array(
            'fileExtensionFalse' => 'Template must be a PDF File'
          ),
          'break_chain_on_failure' => true
        ),
      ),
      array(
        'name' => '\Zend\Validator\File\MimeType',
        'options' => array(
          'mimeType' => 'application/pdf',
          'messages' => array(
            'fileMimeTypeFalse' => 'Template must be a PDF File',
          ),
          'break_chain_on_failure' => true
        ),
      ),
    ),
  ));

Line 3 is required if you want to skip the validators when a file isn’t selected. The temp files will not be uploading to default directory, it has been changed lines 11-14 above. With randomize set to true a random number will be appended to the target file new_brochure.

Controller

  $bBrochure = $this->getServiceLocator()
    ->get('BrochureGateway')
    ->getBrochure($content_id);
  $form = new BrochureForm($content_id);
  $form->bind($bBrochure);

  // Checking to see if the form was submitted
  $request = $this->getRequest();
  if ($request->isPost()){
    $aFiles = $request->getFiles();
    $data = $request->getPost();

    $form->setData(array_merge_recursive(
      $data->toArray(),
      $aFiles->toArray()
    ));

    if ($form->isValid()){
      // DO WHAT IS NEEDED FOR THIS FUNCTION
    }
  }

For the form to validate correctly and adhere to some of the changes we made to the temperary file location we need to merge(line 11) the File (lines 8) and Post(line 9) data.

Retrieving brochure_pdf from the Entity will produce the following array:

  Array
  (
    [name] => 'File Name on local System'
    [type] => 'application/pdf'
    [tmp_name] => './data/temp/new_brochure_56e9b6b7e7a5a.pdf' 
    [error] => 0
    [size] => 52567            
  )

If the file is validated and uploaded correctly the error key will show as 0. In the Gateway, we will check for those conditions on all 6 PDFs, and move them to their ‘permanent’ location.

 $aBrochure = bBrochure ->getBrochure_PDF();
 if (is_array($aBrochure) 
  && array_key_exists('error', $aBrochure) 
  && $aBrochure['error'] == 0){

   //MORE CODE MIGHT BE NEEDED
   rename(
    $aBrochure ['tmp_name'], 
    './public/brochures/' . 'file download label'
   );
 }

Leave a Reply