Como hacer un upload o carga de archivos o imágenes en CodeIgniter 4
Índice de contenido
El proceso de upload consiste en el proceso de subir archivos desde un dispositivo local a un servidor remoto que consta de dos pasos:
- Se selecciona el archivo que se desea subir y luego se envía al servidor.
- El servidor recibe el archivo y lo almacena en una ubicación específica.
Ahora, una vez que tenemos nuestro formulario de tipo POST en CodeIgniter 4, vamos para el siguiente paso.
En una app web, el proceso de upload se puede realizar mediante la implementación de un formulario HTML usando el famoso campo de tipo file en HTML o mediante plugins que envían peticiones HTTP.
El proceso de CodeIgniter 4 para la carga de archivos o upload en inglés, lo podemos dividir en los siguiente bloques:
- Verificar el request del archivo cargado
- Verificar si es valido y si se puede mover
- Validar que el archivo cumpla con tus criterios, por ejemplo, si es una imagen, un documento word... o cualquier otro
- Manejar el proceso de upload o error; para esto lo movemos a alguna carpeta de nuestro proyecto que generalmente es la carpeta writeable o puede ser otra como la carpeta public
- Finalmente mostramos los errores si tenemos errores o guardamos alguna referencia a la imagen o archivo cargado en nuestra base de datos mediante algún modelo; es decir, mediante un condicional hacemos una operación u otra según la respuesta del servidor:
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");
}
}
}
}Esta función retorna null si la carga se hizo correctamente o el primer error que ocurriera en el proceso de upload.
Y por aquí te muestro como puedes consumir la función del upload que generamos anteriormente mediante los procesos de crear y editar que forman parte de nuestro CRUD en CodeIgniter 4.
Primero el proceso de crear en la cual insertamos los datos en nuestra base de datos mediante nuestro modelo y LUEGO es que hacemos el upload o carga del archivo pasando el ID, de lo que creamos anteriormente; puedes ver también la bifurcación que hacemos con los condicionales, en la cual solamente llamamos al proceso del upload cuando creamos el registro, si no, mostramos los errores. si creamos la persona y tenemos problemas con la función de upload lo mandamos directamente a la página de editar y mostramos los errores del proceso de carga de la imagen:
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();
}Como puedes ver, llamamos a la función de _upload cuando ya tenemos referencia al recurso creado, que en este caso, sería una persona.
Puedes encontrar el resto del código de la aplicación en mi repositorio en Github como las vistas empleadas, así como las rutas empleadas.
Cómo mostrar imágenes cargadas en CodeIgniter 4: DOS FORMAS!

La carga de imágenes y manejo de archivos cargados es fundamental en cualquier aplicación, ya que generalmente cuando cargamos los archivos vamos a querer hacer algo con ellos, que en la mayoría de los casos es mostrarlos! en CodeIgniter 4 puede que no sea tan directo; en Laravel tenemos una manera estándar mediante los discos, pero en CodeIgniter 4 al ser un framework más pequeño y simple NO la tenemos, por lo tanto, voy a mostrarte cómo un mecanismo sencillo para lograr este objetivo
Entendiendo como funciona la carga de archivos en CodeIgniter 4
Ya en una entrada pasada, vimos cómo cargar archivos en CodeIgniter 4, siguiendo la documentación oficial, tenemos una carpeta llamada writeable en la cual podemos escribir o es "escribible"; el problema viene cuando NO podemos mostrar los archivos contenidos en ella, porque NO son accesibles mediante http, por lo tanto tenemos dos posibles soluciones:
1 Acceder mediante código en el servidor
También podemos acceder a ese carpeta mediante código PHP, es decir, mediante CodeIgniter 4 y luego la mostramos mediante la función de fpassthru de php y colocando los header correspondientes:
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;
}Esta es la opción que seguimos en mi curso COMPLETO de CodeIgniter 4 que puedes ver en esta plataforma.
Mover o hacer las carga de archivos en la carpeta public
El otro mecanismo que seria el mas recomendado en la mayoría de los casos, seria en vez de mover los archivos cargados a la carpeta writeable, lo cargamos en la carpeta public, que es la única que tenemos para hacer este tipo de operaciones:
$newName = $imageFile->getRandomName();
//$imageFile->move(WRITEPATH . 'uploads/avatar/', $newName);
$imageFile->move(ROOTPATH.'public/uploads', $newName);
$personModel = new PersonModel();
$personModel->update($id, [
'image' => $newName
]);Recuerda que con esto estamos rompiendo un poco el esquema del framework ya que esta carpeta NO está destinada para tal fin; puede ser un poco riesgoso y que en esta carpeta se encuentra el archivo de salida de nuestro proyecto, el index.php del framework y por ende podemos ejecutar TODO lo que carguemos allí.
Por lo tanto, nuestro usuario puede subir un archivo ejecutable y ejecutar el mismo en nuestro servidor, aunque por supuesto esto sería un ataque, cosa que no sucedería en la carpeta writeable ya que solamente la podemos usar para cargar archivos; aunque de esta manera tenemos un mecanismo más limpio para hacer este tipo de operaciones.
Siguiente paso, crear un listado paginado de nuestros registros en Bootstrap 5.
Acepto recibir anuncios de interes sobre este Blog.
Vamos a explicar cual es el proceso de UPLOAD o carga de archivos en CODEIGNITER 4 tomando como caso de estudio la carga del AVATAR del usuario.