How to upload files or images in CodeIgniter 4

Video thumbnail

The upload process consists of the process of uploading files from a local device to a remote server that consists of two steps:

  1. The file to be uploaded is selected and then sent to the server.
  2. The server receives the file and stores it in a specific location.

Now that we have our POST form in CodeIgniter 4, let's move on to the next step.

In a web app, the upload process can be done by implementing an HTML form using the famous HTML file type field or by plugins that send HTTP requests.

The CodeIgniter 4 process for uploading files in English can be divided into the following blocks:

  • Check the uploaded file request
  • Check if it is valid and if it can be moved
  • Validate that the file meets your criteria, for example, if it is an image, a word document... or any other
  • Handle the upload process or error; for this we move it to some folder of our project that is generally the writeable folder or it can be another like the public folder
  • Finally we show the errors if we have errors or we save any reference to the image or file loaded in our database through some model; that is, through a conditional we do one operation or another depending on the server's response:
private function _upload($id)
{
 
 if($imageFile = $this->request->getFile('image')){
  
  if($imageFile->isValid() && !$imageFile->hasMoved()){
   
   // validaciones
   $validated = $this->validate([
    'image' => [
     'uploaded[image]',
     'mime_in[image,image/jpg,image/gif,image/png]'
    ]
   ]);
   if($validated){
    echo "ok";
    $newName = $imageFile->getRandomName();
    //$imageFile->move(WRITEPATH . 'uploads/avatar/', $newName);
    $imageFile->move(ROOTPATH.'public/uploads', $newName);
    $personModel = new PersonModel();
    $personModel->update($id, [
     'image' => $newName
    ]);
    
    return null;
    
   }else {
    return $this->validator->getError("image");
   }

  }
 }
}

This function returns null if the upload was successful or the first error that occurred in the upload process.

And here I show you how you can consume the upload function that we generated earlier through the create and edit processes that are part of our CRUD in CodeIgniter 4.

First, the process of creating in which we insert the data into our database through our model and THEN we upload the file by passing the ID of what we previously created; you can also see the branch we do with the conditionals, in which we only call the upload process when we create the record, otherwise we display the errors. If we create the person and we have problems with the upload function, we send it directly to the edit page and show the errors of the image upload process:
 

public function create()
{
 $person = new PersonModel();
 if ($this->validate('person')) {
  $id = $person->insert(
   [
    'name' => $this->request->getPost('name'),
    'surname' => $this->request->getPost('surname'),
    'age' => $this->request->getPost('age'),
    'description' => $this->request->getPost('description'),
   ]
  );
  $res = $this->_upload($id);
  if($res == null) {
   return redirect()->to('/person')->with('message', 'Persona creada exitosamente' );
  }else{
   return redirect()->to("/person/$id/edit")->withInput();
  }
  return redirect()->to('/person')->with('message', 'Persona creada exitosamente');
 }
 // tenemos problemas con las validaciones
 return redirect()->back()->withInput();
}

public function update($id)
{
 $personModel = new PersonModel();
 $person = $personModel->asObject()->find($id);
 if ($person == null) {
  throw PageNotFoundException::forPageNotFound();
 }
 if ($this->validate('person')) {
  $personModel->update(
   $id,
   [
    'name' => $this->request->getPost('name'),
    'surname' => $this->request->getPost('surname'),
    'age' => $this->request->getPost('age'),
    'description' => $this->request->getPost('description'),
   ]
  );
  $res = $this->_upload($id);
  if($res == null) {
   return redirect()->to('/person')->with('message', 'Persona actualizada exitosamente: ' . $person->name);
  }
  return redirect()->back()->withInput();
 }
 // tenemos problemas con las validaciones
 //return redirect()->back()->withInput();
}

As you can see, we call the _upload function when we already have a reference to the created resource, which in this case would be a person.

You can find the rest of the application code in my Github repository as the views used, as well as the routes used.

How to display uploaded images in CodeIgniter 4: TWO WAYS!

How to display uploaded images in CodeIgniter 4: TWO WAYS!
Video thumbnail

Upload images and handling uploaded files is essential in any application, since generally when we upload files we want to do something with them, which in most cases is to display them! in CodeIgniter 4 it may not be as straightforward; in Laravel we have a standard way through disks, but in CodeIgniter 4, being a smaller and simpler framework, we do NOT have it, therefore, I am going to show you how a simple mechanism to achieve this goal

Understanding how file upload works in CodeIgniter 4

Already in a past entry, we saw how to load files in CodeIgniter 4, following the official documentation, we have a folder called writeable in which we can write or it is "writable"; the problem comes when we can NOT show the files contained in it, because they are NOT accessible through http, therefore we have two possible solutions:

1 Acceder mediante código en el servidor

We can also access that folder through PHP code, that is, through CodeIgniter 4 and then we show it through the php fpassthru function and placing the corresponding headers:

function image($movieId = null, $image = null)
{
 // abre el archivo en modo binario
 if (!$movieId) { // $movieId== null
  $movieId = $this->request->getGet('movie_id');
 }
 if (!$image) { // $image== null
  $image = $this->request->getGet('image');
 }
 if ($movieId == '' || $image == '') {
  throw PageNotFoundException::forPageNotFound();
 }
 $name = WRITEPATH . 'uploads/movies/' . $movieId . '/' . $image;
 if (!file_exists($name)) {
  throw PageNotFoundException::forPageNotFound();
 }
 $fp = fopen($name, 'rb');
 // envía las cabeceras correctas
 header("Content-Type: image/png");
 header("Content-Length: " . filesize($name));
 // vuelca la imagen y detiene el script
 fpassthru($fp);
 exit;
}

This is the option we follow in my COMPLETE CodeIgniter 4 course and book that you can see on this platform.

Move or upload files to the public folder

The other mechanism that would be the most recommended in most cases, would be instead of moving the uploaded files to the writeable folder, we upload them to the public folder, which is the only one we have to do this type of operation:

 $newName = $imageFile->getRandomName();
    //$imageFile->move(WRITEPATH . 'uploads/avatar/', $newName);
    $imageFile->move(ROOTPATH.'public/uploads', $newName);
    $personModel = new PersonModel();
    $personModel->update($id, [
     'image' => $newName
    ]);

Remember that with this we are breaking the framework scheme a bit since this folder is NOT intended for that purpose; It can be a bit risky and that in this folder is the output file of our project, the index.php of the framework and therefore we can execute EVERYTHING that we load there; therefore, our user can upload an executable file and run it on our server, although of course this would be an attack, which would not happen in the writeable folder since we can only use it to upload files; although in this way we have a cleaner mechanism to do this type of operation.

Next step, create a paginated list of our records in Bootstrap 5.

We are going to explain what the UPLOAD or file upload process is in CODEIGNITER 4 taking as a case study the upload of the user's AVATAR.

I agree to receive announcements of interest about this Blog.

Andrés Cruz

ES En español