How to upload a file using jQuery AJAX in CodeIgniter 4

File uploading is a vital function in we­b development that allows use­rs to share and store files on a se­rver. CodeIgniter 4, a powe­rful PHP framework, offers deve­lopers a robust environment for cre­ating web applications.

By leveraging the­ simplicity of jQuery AJAX and the capabilities of Code­Igniter 4, you can easily build an e­fficient file upload system without any complications.

In this tutorial, we will explore how to upload files using jQuery AJAX in CodeIgniter 4 and display a preview of the uploaded file. We will guide you through the process of setting up a CodeIgniter 4 project, creating a controller to handle file uploads, and implementing an upload form view.

Through this tutorial, you will learn how to leverage the capabilities of CodeIgniter 4 and jQuery AJAX to create a smooth and interactive file upload functionality.

How to upload a file using jQuery AJAX in CodeIgniter 4


Table of Content

  1. Enable CSRF
  2. Configure Routes
  3. Create a Controller – Handle file upload request
  4. View – Create HTML form & Write AJAX code for file upload
  5. Output
  6. Conclusion

1. Enable CSRF

  • Open .env file.
  • Remove # from the start of the security.tokenName,security.headerNamesecurity.cookieNamesecurity.expires,and security.regenerate.
  • I update the security.tokenName value with 'csrf_hash_name'. With this name read CSRF hash. You can update it with any other value.
  • If you don’t want to regenerate CSRF hash after each AJAX request then set security.regenerate = false.
security.tokenName = 'csrf_hash_name' 
security.headerName = 'X-CSRF-TOKEN' 
security.cookieName = 'csrf_cookie_name' 
security.expires = 7200 
security.regenerate = true
  • Open app/Config/Filters.php file and uncomment 'csrf' in 'before' if commented.
// Always applied before every request
public $globals = [
    'before' => [
       // 'honeypot',
       'csrf',
       // 'invalidchars',
    ],
    'after' => [
       'toolbar',
       // 'honeypot',
       // 'secureheaders',
    ],
];

2. Configure Routes

  • Open app/Config/Routes.php file.
  • Define 2 routes –
    • / – Display file upload view.
    • users/fileUpload – It is used to upload a file.
$routes->get('/', 'UsersController::index');
$routes->post('users/fileUpload', 'UsersController::fileUpload');

3. Create a Controller – Handle file upload request

  • Create UsersController controller using the following command:
php spark make:controller UsersController
  • Open the file and define two methods:
    • index() – Load index view.
    • fileUpload() – Handles the AJAX request.

Generate a new CSRF token and assign it to $data['token'].

Implement file validation using the following rules:

'file' => 'uploaded[file]|max_size[file,1024]|ext_in[file,jpeg,jpg,docx,pdf],'

If the file fails validation, assign 0 to $data['success'] and the validation response to $data['error'].

If the file is validated then read the file name and extension and upload the file to the "public/uploads" location. Assign 1 to $data['success'], 'Uploaded Successfully!' to $data['message'], file path to $data['filepath'], and file extension to $data['extension'].

If the file fails to upload, assign 2 to $data['success'] and 'File not uploaded.' to $data['message'].

Return the $data array in JSON format.

<?php namespace App\Controllers;

use App\Models\Users;

class UsersController extends BaseController{

    public function index(){
         return view('index');
    }

    public function fileUpload(){

         $data = array();

         // Read new token and assign to $data['token']
         $data['token'] = csrf_hash();

         ## Validation
         $validation = \Config\Services::validation();

         $input = $validation->setRules([
              'file' => 'uploaded[file]|max_size[file,1024]|ext_in[file,jpeg,jpg,docx,pdf],'
         ]);

         if ($validation->withRequest($this->request)->run() == FALSE){

              $data['success'] = 0;
              $data['error'] = $validation->getError('file');// Error response

         }else{

              if($file = $this->request->getFile('file')) {
                    if ($file->isValid() && ! $file->hasMoved()) {
                         // Get file name and extension
                         $name = $file->getName();
                         $ext = $file->getClientExtension();

                         // Get random file name
                         $newName = $file->getRandomName();

                         // Store file in public/uploads/ folder
                         $file->move('../public/uploads', $newName);

                         // File path to display preview
                         $filepath = base_url()."/uploads/".$newName;

                         // Response
                         $data['success'] = 1;
                         $data['message'] = 'Uploaded Successfully!';
                         $data['filepath'] = $filepath;
                         $data['extension'] = $ext;

                    }else{
                         // Response
                         $data['success'] = 2;
                         $data['message'] = 'File not uploaded.'; 
                    }
              }else{
                    // Response
                    $data['success'] = 2;
                    $data['message'] = 'File not uploaded.';
              }
         }
         return $this->response->setJSON($data);

    }
}

4. View – Create HTML form & Write AJAX code for file upload

  • Create a file index.php in the app/Views/ folder.
  • Include a hidden element in the HTML file to store the CSRF token name obtained from the .env file. Assign the CSRF hash value to the value attribute.
<input type="hidden" class="txt_csrfname" name="<?= csrf_token() ?>" value="<?= csrf_hash() ?>" />
  • Utilize jQuery to display the AJAX response message within the <div id="responseMsg"> element.
  • Using jQuery, create an <img> and <a> element within the <div id="filepreview"> to display a file preview based on the file extension.
  • Build a form with the method set to post and the action attribute set to "<?=site_url('users/fileUpload')?>". Include an input element of type "file" and a button in the form.
  • Apply jQuery to display any validation errors in the <div id="err_file"> element if the file fails to pass validation.

jQuery Script –

  • When the button is clicked, retrieve the CSRF Token name and hash from the hidden field and assign them to the variables csrfName and csrfHash.
  • Check if a file has been selected. If not, display an alert message saying "Please select a file."
  • If a file is selected, use the FormData object to pass the selected file. Include the CSRF Token with the FormData.
  • Send an AJAX POST request to "<?=site_url('users/fileUpload')?>", passing the FormData object as the data.
  • In the successful callback, update the CSRF Token by assigning response.token to .txt_csrfname.
  • If response.success equals 1, it means the file was successfully uploaded. Display the response message and preview the file based on its extension.
  • If response.success equals 2, it means the file was not uploaded. Display the response message.
  • If response.success is neither 1 nor 2, it means the file did not pass validation. Display the error message.
<!DOCTYPE html>
<html>
<head>
     <title>How to upload a file using jQuery AJAX in CodeIgniter 4</title>

     <link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">

     <style type="text/css">
     .displaynone{
          display: none;
     }
     </style>
</head>
<body>

     <div class="container">
          <!-- CSRF token --> 
          <input type="hidden" class="txt_csrfname" name="<?= csrf_token() ?>" value="<?= csrf_hash() ?>" />

          <div class="row">
               <div class="col-md-12">

                    <!-- Response message -->
                    <div class="alert displaynone" id="responseMsg"></div>

                    <!-- File preview --> 
                    <div id="filepreview" class="displaynone" > 
                          <img src="" class="displaynone" with="200px" height="200px"><br>

                          <a href="#" class="displaynone" >Click Here..</a>
                    </div>

                    <!-- File upload form -->
                    <form method="post" action="<?=site_url('users/fileUpload')?>" enctype="multipart/form-data">

                          <div class="form-group">

                               <label for="file">File:</label>

                               <input type="file" class="form-control" id="file" name="file" />
                               <!-- Error -->
                               <div class='alert alert-danger mt-2 d-none' id="err_file"></div>

                          </div>

                          <input type="button" class="btn btn-success" id="submit" value="Upload">
                    </form>
               </div>
          </div>
     </div>

     <!-- Script -->
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
     <script type="text/javascript">
     $(document).ready(function(){

          $('#submit').click(function(){

               // CSRF Hash
               var csrfName = $('.txt_csrfname').attr('name'); // CSRF Token name
               var csrfHash = $('.txt_csrfname').val(); // CSRF hash

               // Get the selected file
               var files = $('#file')[0].files;

               if(files.length > 0){
                     var fd = new FormData();

                     // Append data 
                     fd.append('file',files[0]);
                     fd.append([csrfName],csrfHash);
               
                     // Hide alert 
                     $('#responseMsg').hide();

                     // AJAX request 
                     $.ajax({
                          url: "<?=site_url('users/fileUpload')?>",
                          method: 'post',
                          data: fd,
                          contentType: false,
                          processData: false,
                          dataType: 'json',
                          success: function(response){

                               // Update CSRF hash
                               $('.txt_csrfname').val(response.token);

                               // Hide error container
                               $('#err_file').removeClass('d-block');
                               $('#err_file').addClass('d-none');

                               if(response.success == 1){ // Uploaded successfully

                                    // Response message
                                    $('#responseMsg').removeClass("alert-danger");
                                    $('#responseMsg').addClass("alert-success");
                                    $('#responseMsg').html(response.message);
                                    $('#responseMsg').show();

                                    // File preview
                                    $('#filepreview').show();
                                    $('#filepreview img,#filepreview a').hide();
                                    if(response.extension == 'jpg' || response.extension == 'jpeg'){

                                          $('#filepreview img').attr('src',response.filepath);
                                          $('#filepreview img').show();
                                    }else{
                                          $('#filepreview a').attr('href',response.filepath).show();
                                          $('#filepreview a').show();
                                    }
                               }else if(response.success == 2){ // File not uploaded

                                    // Response message
                                    $('#responseMsg').removeClass("alert-success");
                                    $('#responseMsg').addClass("alert-danger");
                                    $('#responseMsg').html(response.message);
                                    $('#responseMsg').show();
                               }else{
                                    // Display Error
                                    $('#err_file').text(response.error);
                                    $('#err_file').removeClass('d-none');
                                    $('#err_file').addClass('d-block');
                               }
                          },
                          error: function(response){
                               console.log("error : " + JSON.stringify(response) );
                          }
                     });
               }else{
                    alert("Please select a file.");
               }

          });
     });
     </script>

</body>
</html>

5. Output

View Output


6. Conclusion

This article e­xplains how to use jQuery AJAX and CodeIgnite­r 4 to upload files and display preview in web applications. With the combination of jQue­ry’s simplicity and CodeIgniter 4’s powerful fe­atures, you can create an e­fficient yet user-frie­ndly file upload functionality according to your project nee­ds.

Don’t hesitate to explore­ and enhance this process furthe­r.

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