
Drupal 8: Ficheros en drupal
Autor: fjavimartin
Fecha de Creación: 13/03/2019
Categorías:
El objetivo de esta entrada de blog será la importación de un fichero gestionado mediante un formulario. Este ejemplo nos ayudará a descubrir como gestiona drupal los ficheros como entidades y como podemos aprovecharnos de ello.
1. Ficheros en drupal 8
Drupal nos permite configurar un sistema de archivos privado y otro público. El sistema de ficheros público suele estar alojado en sites/default/files y los ficheros son servidos por el servidor web. El sistema de ficheros privado está en una ubicación al que no puede acceder el servidor web y tendrá que ser drupal el que haga de intermediario para servir los ficheros.
La configuración de la ruta para cada uno de los sistemas de ficheros está en el formulario ubicado en el fichero sites/default/settings.php:
$settings['file_public_path'] = 'sites/default/files';
$settings['file_private_path'] = '/home/drupal/private_files';
La ruta al sistema de ficheros público siempre será relativa al directorio de instalación de drupal, mientras que la ruta al directorio privado siempre será absoluta y deberá estar fuera del directorio de instalación de drupal. En cualquier momento podemos decidir si queremos que sea el servidor web quién sirva los ficheros o drupal. Para ello deberemos cambiar la configuración en admin/config/media/file-system:

2. Uri’s
Cuando trabajamos con ficheros las rutas se expresan en forma de uri con el formato:
schema://target
donde schema representa la ubicación y target será la ruta relativa al fichero.
3. Archivos gestionados y no gestionados
Drupal nos ofrece la posibilidad de trabajar con dos tipos de ficheros:
- Gestionados: Son aquellos ficheros que son tratados como entidades. Se guardan en la base de datos y se ejecutan hooks cuando se realizan operaciones sobre ellos. Además, drupal lleva un control de los ficheros que quedan “huérfanos”, es decir, ficheros que están dados de alta como entidad, pero en realidad no existen en el sistema de ficheros.
- No gestionados: Son aquellos ficheros que no son tratados como entidades, que simplemente están en el sistema de ficheros y que las operaciones que se realizan sobre ellos son las típicas de php.
4. Fichero files.info.yml
Primer fichero del proyecto donde fijamos nombre de máquina para el proyecto y descripción.
name: Drupal Miseries
type: module
description: Module developed only to show drupal issues.
package: E-Quipos
core: 8.x
5. Fichero files.routing.yml
El siguiente fichero básico de cualquier proyecto es el de routing donde fijamos la ruta que abrirá nuestro formulario:
drupal_miseries.importusers:
path: '/drupal_miseries/form/importusers'
defaults:
_form: '\Drupal\drupal_miseries\Form\ImportUsers'
_title: 'Import Users'
requirements:
_permission: 'access content'
6. Formulario
Lo primero será crear el esqueleto de nuestro formulario en ImportUsers.php:
<?php
namespace Drupal\drupal_miseries\Form;
use Drupal\Core\Form\FormBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\file\FileUsage\DatabaseFileUsageBackend;
use Drupal\Core\Session\AccountProxyInterface;
class ImportUsers extends FormBase {
protected $fileUsage;
protected $current_user;
public function __construct(DatabaseFileUsageBackend $fileUsage, AccountProxyInterface $current_user) {
$this->fileUsage = $fileUsage;
$this->current_user = $current_user;
}
public static function create(ContainerInterface $container) {
return new static (
$container->get('file.usage'),
$container->get('current_user')
);
}
public function getFormId() {
return 'drupalmiseriesImportUsers';
}
public function buildForm(array $form, FormStateInterface $form_state) {
$form['description'] = [
'#markup' => $this->t('Form designed to show how to import users.'),
];
$form['files'] = [
'#type' => 'managed_file',
'#title' => $this->t('Upload file'),
'#upload_location' => 'public://drupal_miseries',
'#upload_validators' => [
'file_validate_extensions' => ['csv'],
],
'#required' => TRUE,
];
$form['actions'] = [
'#type' => 'actions',
];
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Submit'),
];
return $form;
}
public function submitForm(array &$form, FormStateInterface $form_state) { }
}
Ya tenemos nuestro formulario funcionando. En general el código es bastante sencillo:
- Hemos inyectado dos servicios al formulario. El primero de ellos será ‘current_user’ y que utilizaremos para tener acceso al usuario que está accediendo al formulario y ‘file_usage’ que es el servicio que lleva la gestión de los fichero manejados.
- El elemento del formulario ‘file’ será el encargado de gestionar la subida del fichero. Su configuración es muy sencilla y básicamente le hemos indicado que es un elemento requerido para enviar el formulario (si no hay fichero subido ya me contaréis……), hemos configurado la ruta donde se subirán los ficheros que en nuestro caso será el repositorio público (podemos cambiar este parámetro en tiempo de generación del formulario para personalizarlo en función de nuestras necesidades) y por último hemos añadido un validador para restringir el tipo de ficheros que podremos subir.
El siguiente paso será añadir el código necesario al método submitForm() para realizar la gestión de los ficheros subidos:
public function submitForm(array &$form, FormStateInterface $form_state) {
$storage = $this->entityTypeManager->getStorage('file');
foreach ($form_state->getValue('files') as $fid) {
$file = $storage->load($fid);
$this->fileUsage->add($file, 'drupal_miseries', 'user', $this->current_user->id(), 1);
drupal_set_message( $this->t('File uploaded: '. $file->get('filename')->value) );
}
}
Cuando subimos un fichero haciendo uso de un elemento de formulario ‘managed_file’ será este elemento el que se ocupará de dar de alta cada fichero como entidad. En nuestro método ‘submitForm’ obtendremos desde $form_state todos los identificadores de las entidades de los ficheros que hayamos subido que más tarde utilizaremos para dar de alta en la lista de ficheros de nuestro módulo.
Utilizaremos el servicio ‘file.usage’ para dar de alta el fichero tal y como indicamos anteriormente. Le pasaremos al método ‘add’:
- $file → La entidad con el fichero que acabamos de subir.
- Nombre del módulo que está dando de alta el fichero.
- El tipo de objeto que contendrá la referencia la fichero, utilizaremos nuestro usuario y para ello necesitaremos el servicio ‘current_user’.
- Identificador del objeto correspondiente al anterior punto.
- Estado: Por defecto los ficheros se dan de alta con estado = 0 lo que indicará que el fichero no es permanente. En nuestro caso queremos que sea permanente por lo que indicamos que el estado = 1.
He utilizado un bucle foreach para recorrer todos los valores que pueda contener ‘file’, el motivo es bien sencillo, cuando utilizamos el atributo ‘#multiple’ => TRUE podemos subir más de un fichero en la misma operación y ‘file’ nos devolverá un array con todos los identificadores de los ficheros por lo que necesitaremos gestionarlos de esta manera.
Conclusiones
Es imposible meterlo todo sobre ficheros en un solo artículo, pero aquí tenéis todas las herramientas necesarias para empezar y desde donde empezar a tirar del hilo.
Espero que hayáis disfrutado del artículo y no perdáis de vista este blog. En breve publicaré una ampliación de este mismo artículo en el que os mostraré como crear usuarios mediante código que procederán de un fichero .csv.
Disfrutar!!!!!!!
Referencias
https://www.e-quipos.es/blog/drupal-8-inyecci%C3%B3n-de-servicios
https://www.e-quipos.es/blog/drupal-8-creaci%C3%B3n-de-formularios
https://api.drupal.org/api/drupal/core%21modules%21file%21file.services.yml/service/file.usage/8.2.x