In today’s digital world, file uploads are a crucial aspect of web applications. Users demand a smooth and user-friendly experience when uploading files, whether it’s a profile picture or an important document.
Dropzone is a widely used method for file uploads, offering a simple and intuitive drag-and-drop interface.
This JavaScript library supports multiple file uploads, progress bars, and previews of uploaded files. Dropzone uses AJAX technology to upload files without the need for a page refresh, making it a popular choice for developers and users alike.
In this tutorial, I will provide a step-by-step guide to implementing dropzone file uploads in your CakePHP 4 project.
Contents
1. Include Dropzone and CSRF token
I am including the Dropzone library and CSRF token in templates/layout/default.php
file.
You can download Dropzone library from their official website or you can use CDN –
<!-- Dropzone --> <link rel="stylesheet" href="https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" type="text/css" /> <script src="https://unpkg.com/dropzone@5/dist/min/dropzone.min.js"></script>
Completed Code
<?php $cakeDescription = 'CakePHP: the rapid development php framework'; ?> <!DOCTYPE html> <html> <head> <?= $this->Html->charset() ?> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- CSRF Token --> <?= $this->Html->meta('csrfToken', $this->request->getAttribute('csrfToken')); ?> <title> <?= $cakeDescription ?>: <?= $this->fetch('title') ?> </title> <?= $this->Html->meta('icon') ?> <link href="https://fonts.googleapis.com/css?family=Raleway:400,700" rel="stylesheet"> <?= $this->Html->css(['normalize.min', 'milligram.min', 'cake']) ?> <!-- Dropzone --> <link rel="stylesheet" href="https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" type="text/css" /> <script src="https://unpkg.com/dropzone@5/dist/min/dropzone.min.js"></script> <?= $this->fetch('meta') ?> <?= $this->fetch('css') ?> <?= $this->fetch('script') ?> </head> <body> <nav class="top-nav"> <div class="top-nav-title"> <a href="<?= $this->Url->build('/') ?>"><span>Cake</span>PHP</a> </div> <div class="top-nav-links"> <a target="_blank" rel="noopener" href="https://book.cakephp.org/4/">Documentation</a> <a target="_blank" rel="noopener" href="https://api.cakephp.org/">API</a> </div> </nav> <main class="main"> <div class="container"> <?= $this->Flash->render() ?> <?= $this->fetch('content') ?> </div> </main> <footer> </footer> </body> </html>
2. Create Controller
- Create a
FileuploadController.php
file insrc/Controller/
folder. - Create
FileuploadController
Class that extendsAppController
. - Include
Cake\Filesystem\Folder
to create folder andCake\Validation\Validator
to add validation rules.
Create 2 methods –
- index()
- upload() – Using this method to handle Dropzone AJAX requests.
NOTE – The
file
key name is used by Dropzone to send a file. File access using thefile
key name.
Define file validation, it is same as defined during Dropzone initialization. Created $response
Array to store upload status.
If file is not validated then read the error message, assign it to $response['message']
and 0
to $response['success']
. Return $response
Array in JSON format.
If file is validated then read file details and assign them to the variables. I am uploading files to uploads
folder. Before uploading check if uploads
folder exists or not, if not exist then create it. If folder is unable to create then store 'Folder is not created.'
to $response['message']
and 0
to $response['success']
. Return $response
Array in JSON format.
Upload the file by calling moveTo()
method where pass file name with path. Store 'File uploaded successfully.'
to $response['message']
and 1
to $response['success']
.
Return $response
Array in JSON format.
Completed Code
<?php declare(strict_types=1); namespace App\Controller; use Cake\Filesystem\Folder; use Cake\Validation\Validator; class FileuploadController extends AppController { public function index(){ } // Upload Dropzone file public function upload(){ ## Validate File $validator = new Validator(); $validator ->notEmptyFile('file') ->add('file', [ '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', ] ]); $errors = $validator->validate($this->request->getData()); $response = array(); if (!empty($errors)) { // Not validated ## Return response with error message $fileerrors = $errors['file']; $errormsg = ""; foreach($fileerrors as $error){ $errormsg = $error; } $response['message'] = $errormsg; $response['success'] = 0; echo json_encode($response); die; } ## Upload file $fileEl = $this->request->getData('file'); // File details $filename = $fileEl->getClientFilename(); $type = $fileEl->getClientMediaType(); $size = $fileEl->getSize(); $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); $tmpName = $fileEl->getStream()->getMetadata('uri'); $error = $fileEl->getError(); if($error == 0){ ## Upload location $location = WWW_ROOT . 'uploads' . DS;// webroot/uploads/ ## Check upload location exists or not $folder = new Folder(); $checkfolder = $folder->inPath($location, true); if(!$checkfolder){ // Not exists if (!$folder->create($location)) { $response['message'] = 'Folder is not created.'; $response['success'] = 0; echo json_encode($response); die; } } ## Upload file $targetPath = $location.$filename; $fileEl->moveTo($targetPath); ## Uploaded file path $filepath = "/uploads/".$filename; $response['message'] = 'File uploaded successfully.'; $response['success'] = 1; echo json_encode($response); die; }else{ $response['message'] = 'File is not uploaded.'; $response['success'] = 0; echo json_encode($response); die; } } }
3. Create Template
Create Fileupload
folder in templates/
location. In the Fileupload
folder create index.php
file – templates/Fileupload/index.php
.
Create a <form >
–
<form action="<?= $this->Url->build(['controller' => 'fileupload','action' => 'upload']) ?>" class='dropzone' ></form>
Script
- Read CSRF token from
<meta name="csrfToken" >
tag and assign it tocsrfToken
variable. - Disable Dropzone auto initialization by setting
Dropzone.autoDiscover
tofalse
. - Initialize Dropzone on
dropzone
class and set file restrictions. - I set
maxFilesize
to 2 (2 MB) and allowed file typesacceptedFiles: ".jpeg,.jpg,.png,.pdf"
. - Pass CSRF token using header –
"X-CSRF-Token" : csrfToken
. - Using
success
event handle Dropzone response. Ifsuccess == 0
means file is not uploaded and alert the error message.
Completed Code
<div class="row"> <div style="width: 100%;"> <!-- Dropzone --> <form action="<?= $this->Url->build(['controller' => 'fileupload','action' => 'upload']) ?>" class='dropzone' ></form> </div> </div> <!-- Script --> <script type="text/javascript"> // Read CSRF Token var csrfToken = document.querySelector('meta[name="csrfToken"]').content; Dropzone.autoDiscover = false; var myDropzone = new Dropzone(".dropzone",{ maxFilesize: 2, // 2 mb acceptedFiles: ".jpeg,.jpg,.png,.pdf", headers: { "X-CSRF-Token" : csrfToken } }); myDropzone.on("success", function(file, response) { response = JSON.parse(response); if(response.success == 0){ // Error alert(response.message); } }); </script>
4. Output
5. Conclusion
Dropzone makes it easier to manage file uploads in CakePHP 4 projects. It instantly displays a preview after a file is uploaded successfully.
By following this tutorial, you can quickly add Dropzone file upload to your project.
When uploading files using Dropzone, you must pass the CSRF token using the header.
You can also view this tutorial if you want to upload file using jQuery AJAX in CakePHP 4 or you can view more CakePHP 4 tutorials.
If you found this tutorial helpful then don't forget to share.