How to Upload file and Display preview in CakePHP 4

File uploads are a common feature in web applications. It allows users to upload and share files, such as images, videos, and documents.

CakePHP 4 already has built-in File handling classes to handle file uploads.

In this tutorial, I show how you can upload file with validation and display its preview after upload in CakePHP 4.

In the example, I am using the Modelless form for creating an upload form.

How to upload file and display preview in CakePHP 4


Table of Content

  1. Create UploadfileForm Form
  2. Create Controller
  3. Create Template
  4. Output
  5. Conclusion

1. Create UploadfileForm Form

  • Create UploadfileForm.php file in src/Form/ folder. Create Form folder if it does not exist.
  • Create UploadfileForm class.

Create 3 methods –

  • _buildSchema() – Define HTML form schema data. I am not defining <form > element from here.
  • validationDefault() – This method will handle form validation. Specifically, focus on the fileel, which represents the file input element. Set it as required and establish rules for file type and file size.
  • _execute() – From this method upload the selected file.

Assign file instance to $attachment. Read file details and assign them to the variables.

If $error == 0 then check if uploads folder exists in webroot or not. If not exists then create it.

Upload the file and return true.

NOTE  – Uploaded file will be stored in webroot/uploads/ folder.

<?php 
namespace App\Form;

use Cake\Form\Form;
use Cake\Form\Schema;
use Cake\Validation\Validator;
use Cake\Filesystem\Folder;

class UploadfileForm extends Form
{
      protected function _buildSchema(Schema $schema): Schema
      {
           return $schema;
      }

      public function validationDefault(Validator $validator): Validator
      {

           $validator
               ->notEmptyFile('fileel')
               ->add('fileel', [
                      'mimeType' => [
                           'rule' => ['mimeType',['image/jpg','image/png','image/jpeg','application/pdf']],
                           'message' => 'File type must be .jpg,.jpeg,.png,.pdf',
                      ],
                      'fileSize' => [
                           'rule' => ['fileSize','<', '2MB'],
                           'message' => 'File size must be less than 2MB',
                      ]
               ]);

           return $validator;
      }

      protected function _execute(array $data): bool
      {
           $attachment = $data['fileel'];

           // File details
           $filename = $attachment->getClientFilename();
           $type = $attachment->getClientMediaType();
           $size = $attachment->getSize();
           $extension = pathinfo($filename, PATHINFO_EXTENSION);
           $tmpName = $attachment->getStream()->getMetadata('uri');
           $error = $attachment->getError();

           // Upload file
           if($error == 0){

                 $location = WWW_ROOT . 'uploads' . DS;

                 $folder = new Folder();
                 $checkfolder = $folder->inPath($location, true);
                 if(!$checkfolder){ // Not exists
                      if (!$folder->create($location)) {
                            return false;
                      }
                 }

                 $targetPath = $location.$filename;
                 $attachment->moveTo($targetPath);

                 return true;
           }else{
                 return false;
           }

      }
}

2. Create Controller

  • Create a FileuploadController.php file in src/Controller/ folder.
  • Create FileuploadController Class that extends AppController.
  • Include App\Form\UploadfileForm.

Here, create 1 method –

  • index() – Create an instance of UploadfileForm().

Check if the <form> is submitted using the POST method. If the form is submitted, then call $uploadfile->execute() and pass the POST data. If this function returns true, then proceed to read data from the file input element for preview.

Assign $filepath to $filedetails['filepath'] and $extension to $filedetails['extension'].

Finally, set both filedetails and uploadfile for further processing.

<?php
declare(strict_types=1);

namespace App\Controller;
use App\Form\UploadfileForm;

class FileuploadController extends AppController
{

     public function index(){
          $uploadfile = new UploadfileForm();

          $filedetails = array();
          if ($this->request->is('post')) {

                if ($uploadfile->execute($this->request->getData())) {

                      // Read file for preview
                      $attachment = $this->request->getData('fileel');
                      $filename = $attachment->getClientFilename();
                      $extension = pathinfo($filename, PATHINFO_EXTENSION);

                      $filepath = "/uploads/".$filename;
                      $extension = $extension;

                      $filedetails['filepath'] = $filepath;
                      $filedetails['extension'] = $extension;

                      $this->Flash->success('File uploaded successfully.');
                } else {
                      $this->Flash->error('File not uploaded.');
                }
          }

          $this->set('filedetails', $filedetails);
          $this->set('uploadfile', $uploadfile);
     }

}

3. Create Template

Create a new Fileupload folder in templates/ folder. Now in the Fileupload folder create index.php file.

Create a <form > set its action to fileupload/index. Pass $uploadfile as 1st parameter in create(). Here, $uploadfile is an instance of UploadfileForm Class it is set from the controller.

In the <form > create a file element and a submit button.

To display a preview check if $filedetails Array is empty or not.

If not empty then check $filedetails['extension'] extension value. If the extension is image type then create <img > element to display file otherwise create <a > tag to create view link.

<div class="row">
    <div class="col-6">

        <?php 

        // Upload form
        echo $this->Form->create($uploadfile,array('url'=>['controller' => 'fileupload','action' => 'index'],"enctype" => "multipart/form-data" ));
        echo $this->Form->control('fileel',['label' => 'Select file','type' => 'file','class' => 'form-control','required' => true]);
        echo $this->Form->button('Submit');
        echo $this->Form->end();

        ?>

        <?php
        // Preview file
        if(count($filedetails) > 0){
             $image_exts = array("jpg","jpeg","png");
             if(in_array($filedetails['extension'],$image_exts)){
                  echo $this->HTML->image($filedetails['filepath']);
             }else{
                  echo $this->Html->link(
                      'View file',
                      $filedetails['filepath'],
                      ['target' => '_blank']
                  );
             }
        }
        ?>

    </div>
</div>

4. Output

http://localhost:8765/fileupload

View Output


5. Conclusion

If you also want to save the file to the database then you don’t need to create a Modelless Form class. You need to pass ORM Entity in form and handle it in the controller.

You can view this tutorial if you want to save file to a database.

If you found this tutorial helpful then don't forget to share.

Leave a Comment