Crear un controlador en Drupal para gestionar la descarga de archivos es una tarea común y útil, especialmente cuando necesitas proporcionar documentos, informes u otros recursos a los usuarios de tu sitio. Esta guía te mostrará cómo crear un controlador que no solo permita descargar archivos, sino que también tenga en cuenta la información del usuario y proporcione mensajes de error en la pantalla si ocurre algún problema, todo ello mientras se sigue una estructura de código limpia y segura.
En esta guía, aprenderás a:
- Definir una ruta personalizada para acceder al controlador de descarga.
- Desarrollar el controlador que maneje la descarga de archivos.
- Inyectar servicios de Drupal para trabajar con la información del usuario y mostrar mensajes.
- Manejar errores y redirecciones, proporcionando una experiencia de usuario fluida.
Sigue estos pasos para integrar un controlador en tu módulo personalizado y mejorar la funcionalidad de tu sitio Drupal, permitiendo a los usuarios descargar archivos de forma controlada y con mensajes claros en caso de errores.
Paso 1: Definir la ruta en my_module.routing.yml
Crea un archivo de configuración de ruta para definir la URL a la que se accederá para la descarga de archivos.
my_module.file_download:
path: '/download-file/{filename}'
defaults:
_controller: '\Drupal\my_module\Controller\FileDownloadController::downloadFile'
_title: 'Descargar Archivo'
requirements:
_permission: 'access content'
Paso 2: Crear el controlador en src/Controller/FileDownloadController.php
Crea un controlador que maneje la descarga y gestione los mensajes de error.
namespace Drupal\my_module\Controller;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Messenger\MessengerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Session\AccountProxyInterface;
class FileDownloadController extends ControllerBase {
/**
* El servicio de usuario actual.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;
/**
* El servicio de mensajería.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* Constructor.
*
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* El servicio de usuario actual.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* El servicio de mensajería.
*/
public function __construct(AccountProxyInterface $current_user, MessengerInterface $messenger) {
$this->currentUser = $current_user;
$this->messenger = $messenger;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('current_user'),
$container->get('messenger')
);
}
/**
* Controlador para descargar un archivo.
*
* @param string $filename
* El nombre del archivo a descargar.
*
* @return \Symfony\Component\HttpFoundation\StreamedResponse|\Symfony\Component\HttpFoundation\RedirectResponse
* Una respuesta de archivo o una redirección con un mensaje de error.
*/
public function downloadFile($filename) {
// Ruta al archivo en el sistema de archivos público.
$file_path = 'public://downloads/' . $filename;
// Verifica si el archivo existe.
if (file_exists(\Drupal::service('file_system')->realpath($file_path))) {
// Crea una respuesta de archivo en memoria.
$response = new StreamedResponse(function () use ($file_path) {
readfile(\Drupal::service('file_system')->realpath($file_path));
});
// Configura los encabezados de la respuesta.
$response->headers->set('Content-Type', 'application/octet-stream'); // Ajusta el tipo MIME según el archivo.
$response->headers->set('Content-Disposition', ResponseHeaderBag::DISPOSITION_ATTACHMENT, $filename);
return $response;
}
else {
// Muestra un mensaje de error si el archivo no existe.
$this->messenger->addError($this->t('El archivo no existe o no está disponible para la descarga.'));
// Redirige al usuario a la página anterior o a la página de inicio.
$current_path = \Drupal::service('path.current')->getPath();
return new RedirectResponse($current_path);
}
}
}
Explicación del controlador:
- Dependencias: Se inyectan los servicios
current_userymessengerpara obtener la información del usuario y mostrar mensajes. - Verificación de archivos: Se verifica la existencia del archivo con
file_exists()antes de intentar enviarlo. - Mensajes de error: Se muestra un mensaje al usuario usando
addError()si el archivo no se encuentra. - Redirección: En caso de error, el usuario es redirigido a la página actual (
$current_path).
Paso 3: Consideraciones adicionales
- Permisos: Verifica que la ruta tenga los permisos adecuados en
my_module.routing.ymlpara que solo usuarios autorizados accedan a la descarga. - Seguridad: Asegúrate de validar el nombre del archivo (
$filename) para evitar la inyección de rutas y garantizar que solo se acceda a archivos seguros. - Tipos MIME: Cambia
application/octet-streama otro tipo MIME si sabes el tipo de archivo que estás sirviendo (por ejemplo,application/pdf).
Paso 4: Probar el controlador
- Accede a la URL
/download-file/archivo.pdfen tu sitio. - Si el archivo existe, se descargará.
- Si no existe, se mostrará un mensaje de error y el usuario será redirigido a la página actual.
Esta guía te ayudará a crear un controlador en Drupal que gestione la descarga de archivos, tome en cuenta la información del usuario y muestre mensajes en caso de error en la pantalla.