How to File upload using cURL in CodeIgniter 4

cURL is widely used for making HTTP requests. With this, you can send requests to API to retrieve or manipulate data, submit form, file upload, etc.

CodeIgniter 4 already provided a CURLRequest class for sending cURL requests.

In this tutorial, I show how you can upload file using cURL from the CodeIgniter 4 project to another project.

How to file upload using cURL in CodeIgniter 4


Table of Content

  1. Create file upload API
  2. Enable CSRF
  3. Create Controller
  4. Create Routes
  5. Create View
  6. Output
  7. Conclusion

1. Create file upload API

I am creating a simple API for file upload in other PHP project – apis/api.php.

If $_FILES is set then read the file name and check the file extension. If it is valid then upload the file to the upload folder and assign 1 to $status and success message to $msg variable otherwise, assign 0 to $status and error message to $msg.

Return $response in JSON format. It has status, msg, and username values.

Here, the username is an extra parameter that is passed with the file.

Completed Code

<?php

$status = 0; $msg = "";

if(isset($_FILES['file']['name'])){
     // file name
     $filename = $_FILES['file']['name'];

     // Location
     $location = 'upload/'.$filename;

     // file extension
     $file_extension = pathinfo($location, PATHINFO_EXTENSION);
     $file_extension = strtolower($file_extension);

     // Valid extensions
     $valid_ext = array("pdf","doc","docx","jpg","png","jpeg");

     $status = 0;
     if(in_array($file_extension,$valid_ext)){       
           // Upload file
           if(move_uploaded_file($_FILES['file']['tmp_name'],$location)){
                 $status = 1;
                 $msg = "Upload successfully";
           } 
     }else{
           $status = 0;
           $msg = "Invalid file extension";
     }

}

$response = array(
     'status' => $status,
     'msg' => $msg,
     'username' => $_POST['username']
);

echo json_encode($response);
die;

2. Enable CSRF

  • Now, go to the CodeIgniter 4 project and open .env file.
  • Remove # from the start of the security.tokenName,security.headerName, security.cookieName, security.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 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.
  • Uncomment 'csrf' in 'before' if commented.
// Always applied before every request
public $globals = [
    'before' => [
       // 'honeypot',
       'csrf',
       // 'invalidchars',
    ],
    'after' => [
       'toolbar',
       // 'honeypot',
       // 'secureheaders',
    ],
];

3. Create Controller

  • Create PagesController Controller –
php spark make:controller PagesController
  • Open app/Controllers/PagesController.php file.

Create 2 methods –

  • index() – Load index view.
  • submitform() – This method calls on <form > submit.

Validate the file. If not validated then return to the page with an error otherwise send cURL POST request to 'http://localhost/apis/api.php';.

Read file tempname, orginal name, and mime type for creating CURLFile object. Using this pass file through cURL.

Create $postData Array to store file and username. Here, username is an extra parameter.

Send a cURL request and pass $postData using multipart option.

If the cURL status code is 200 then read the return response.

Completed Code

<?php

namespace App\Controllers;

use App\Controllers\BaseController;

class PagesController extends BaseController
{
     public function index(){
         return view('index'); 
     }

     // cURL file upload
     public function submitform(){

         $request = service('request');

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

         $input = $validation->setRules([
              'username' => 'required',
              'file' => 'uploaded[file]|max_size[file,2048]|ext_in[file,jpeg,jpg,png,pdf,doc,docx],'
         ]);

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

              $data['validation'] = $this->validator;
              return redirect()->back()->withInput()->with('validation', $this->validator);

         }else{

              $apiURL = 'http://localhost/apis/api.php?request=2';
              $client = \Config\Services::curlrequest();

              if($file = $this->request->getFile('file')) {
                    $tempfile = $file->getTempName();
                    $filename = $file->getName();
                    $type = $file->getClientMimeType();

                    // Create a CURLFile object
                    $cfile = curl_file_create($tempfile,$type,$filename);

                    $postData = array(
                         'file' => $cfile,
                         'username' => $request->getPost()['username']
                    );

                    // Send request
                    $response = $client->post($apiURL,['debug' => true,'multipart' => $postData]);

                    // Read response
                    $code = $response->getStatusCode();
                    $reason = $response->getReason();

                    if($code == 200){ // Success

                         // Read data 
                         $body = json_decode($response->getBody());

                         echo "<pre>";
                         print_r($body);die;
                         $status = $body->status;
                         $msg = $body->msg;
                         $username = $body->username;

                         echo "status : ".$status."<br>";
                         echo "msg : ".$msg."<br>";
                         echo "username : ".$username."<br>";

                    }else{
                         echo "failed";
                         die;
                    }
              }
         }
         return redirect()->route('/');
     }

}

4. Create Routes

  • Open app/Config/Routes.php file.
  • Define 2 routes –
    • / – Display index view.
    • page/submitform – Handle form submit.
$routes->get('/', 'PagesController::index');
$routes->post('page/submitform', 'PagesController::submitForm');

5. Create View

Create index.php file in app/Views/ folder.

Create <form > for file upload and enter a username. Set it action attribute value – <?=site_url('page/postrequest')?>.

Completed Code

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>How to file upload using cURL in CodeIgniter 4</title>

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" >

</head>
<body>

    <div class="container">

         <div class="row"> 
               <div class="col-md-6 mt-5" style="margin: 0 auto;">

                     <?php $validation = \Config\Services::validation(); ?>

                     <form method="post" action="<?=site_url('page/submitform')?>" enctype="multipart/form-data">

                          <?= csrf_field(); ?>

                          <div class="form-group mb-4">
                               <label class="control-label col-sm-2" for="name">User name:</label>
                               <div class="col-sm-10">
                                     <input type="text" class="form-control" id="username" placeholder="Enter username" name="username" value="<?= old('username') ?>">
                               </div>

                               <!-- Error -->
                               <?php if( $validation->getError('username') ) {?>
                                     <div class='text-danger mt-2'>
                                           * <?= $validation->getError('username'); ?>
                                     </div>
                               <?php }?>
                          </div>
                          <div class="form-group mb-4">
                               <label class="control-label col-sm-2" for="file">File:</label>
                               <div class="col-sm-10">
                                     <input type="file" class="form-control" id="file" name="file" >
                               </div>

                               <!-- Error -->
                               <?php if( $validation->getError('file') ) {?>
                                     <div class='text-danger mt-2'>
                                           * <?= $validation->getError('file'); ?>
                                     </div>
                               <?php }?>
                          </div>

                          <div class="form-group "> 
                               <div class="col-sm-offset-2 col-sm-10">
                                     <button type="submit" class="btn btn-info">Submit</button>
                               </div>
                          </div>
                     </form>
               </div>
         </div>

    </div>

</body>
</html>

6. Output

View Output


7. Conclusion

You can pass more parameters with file data. In the example, I passed the username, and in the API file, read it using POST. Use multipart option to pass data.

Set header if your API requires authorization. You can view this tutorial for adding a header with cURL request in CodeIgniter 4.

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

Leave a Comment