Subida de archivos
Las subidas de archivos en Osumi Framework 9.10 siguen la misma estructura que el resto del manejo de peticiones:
ORequestexpone los archivos subidos.- Los DTOs pueden validar los datos relacionados con la subida.
- Los componentes orquestan la petición.
- Los servicios son adecuados para lógica reutilizable de procesamiento de archivos.
- Los Middlewares pueden proteger las rutas de subida.
1. Acceder a un archivo subido
PHP almacena la información de los archivos subidos en $_FILES.
Osumi Framework la expone mediante:
$file = $req->getFile(
'photo'
);
El valor devuelto sigue la estructura estándar de subida de PHP.
El contexto de Middleware está disponible de forma independiente mediante getMiddleware() y getMiddlewareValue().
2. DTO de subida
Ejemplo:
<?php
declare(strict_types=1);
namespace Osumi\OsumiFramework\App\DTO;
use Osumi\OsumiFramework\DTO\ODTO;
use Osumi\OsumiFramework\Web\ORequest;
class PhotoUploadDTO extends ODTO {
public ?array $photo = null;
/**
* Build the upload DTO.
*
* @param ORequest $req Current request.
*/
public function __construct(ORequest $req) {
parent::__construct(
$req
);
$this->photo = $req->getFile(
'photo'
);
}
}
Valida la presencia del archivo, el error de subida, el tipo MIME, la extensión y el tamaño antes de almacenarlo.
3. Componente de subida
class UploadPhotoComponent extends OComponent {
public string $status = 'ok';
public string $message = '';
public ?string $filename = null;
/**
* Store the uploaded file.
*
* @param PhotoUploadDTO $dto Upload DTO.
*
* @return void
*/
public function run(PhotoUploadDTO $dto): void {
$file = $dto->photo;
if (
!is_array($file) ||
!array_key_exists('error', $file) ||
$file['error'] !== UPLOAD_ERR_OK ||
!isset(
$file['tmp_name'],
$file['name']
)
) {
$this->status = 'error';
$this->message = 'Se requiere un archivo válido.';
return;
}
$new_name = uniqid(
'photo_',
true
)
. '_'
. basename(
(string) $file['name']
);
$upload_dir = $this->getConfig()->getDir(
'uploads'
);
$destination = $upload_dir
. $new_name;
if (
!move_uploaded_file(
(string) $file['tmp_name'],
$destination
)
) {
$this->status = 'error';
$this->message = 'No se ha podido guardar el archivo.';
return;
}
$this->filename = $new_name;
$this->message = 'Archivo subido correctamente.';
}
}
4. Proteger la ruta de subida
ORoute::post(
'/api/upload-photo',
UploadPhotoComponent::class,
[
OMiddleware::PHASE_BEFORE => [
LoginMiddleware::class
]
]
);
El componente de subida no se ejecutará si el Middleware de autenticación detiene la petición.
El contexto autenticado se puede leer mediante:
$id_user = $req->getMiddlewareValue(
'Login',
'id'
);
o asignar directamente a un DTO mediante middleware y middlewareProperty.
5. Validación
Las comprobaciones habituales incluyen:
UPLOAD_ERR_OK- Tamaño máximo
- Tipo MIME
- Extensión
- Normalización del nombre
- Permisos del destino
No confíes únicamente en los metadatos MIME proporcionados por el cliente.
6. Almacenar metadatos
$photo = new Photo();
$photo->filename = $new_name;
$photo->user_id = $id_user;
$photo->save();
Para lógica de almacenamiento reutilizable, usa un servicio.
7. Buenas prácticas
- Mantén los directorios de subida fuera del acceso público salvo que los archivos deban ser públicos.
- Genera nombres únicos.
- Valida tamaño, tipo MIME y extensión.
- Usa servicios cuando crezca la lógica de procesamiento de archivos.
- Usa Middlewares cuando las subidas requieran autenticación o autorización.
- Usa contexto de Middleware en lugar de IDs de usuario proporcionados por el cliente.
8. Resumen
Un flujo canónico de subida es:
- Proteger la ruta con Middleware si es necesario.
- Leer el archivo con
ORequest::getFile(). - Validar la subida.
- Guardar el archivo de forma segura.
- Persistir metadatos si es necesario.
- Usar contexto de Middleware de confianza para asociar la propiedad autenticada.