> Manuales > Manual de Firebase

Explicamos todo lo que debes saber para comenzar con el servicio Storage de Firebase, junto con un ejemplo sencillo para hacer el upload, operación put, desde una página web.

En la nueva versión de Firebase uno de los servicios estrella es el de "Storage" que nos permite subir archivos a la nube y compartirlos entre usuarios de la aplicación. Era una de las demandas más comunes por parte de los desarrolladores en Firebase que afortunadamente ya tenemos con nosotros. Gracias a ello, tanto desde la web como desde dispositivos somos ahora capaces de cargar y manipular archivos, sin tener que escribir código de la parte del backend.

Firebase Storage funciona usando el servicio Google Cloud Storage por debajo. Existe un depósito de almacenamiento, llamado "bucket" donde podemos enviar datos que estarán asociados a nuestra aplicación. Sin embargo, nosotros no interactuaremos directamente con Google Storage, sino que usaremos el SDK que nos ofrece una operativa simplificada y muy similar a la que ya manejamos cuando escribimos datos en la base de datos en tiempo real.

En resumen, Firebase es una envoltura del servicio de almacenamiento de Google, beneficiándose de varias ventajas y potencia de la nube de Google y manteniendo un código sencillo y enteramente del lado del cliente. Además gracias a la integración del servicio de almacenamiento de Firebase podemos crear reglas de seguridad que usen los datos y usuarios de nuestra aplicación, de modo que podemos mantener los archivos de cada persona privados o bien compartirlos con otros usuarios que se desee.

En este artículo del Manual de Firebase queremos dar una pequeña introducción al servicio de Storage y ofrecer un primer script con el que podrás probarlo.

Cómo está organizado el servicio de storage

El almacenamiento en la nube que nos ofrece Firebase está organizado en una estructura jerárquica, igual que las carpetas en un disco duro normal, o los datos en la "Realtime Database". También usamos el carácter "/" para separar los niveles, igual que en referencias de la base de datos o carpetas del disco.

carpeta/carpeta/archivo.png

Para navegar por las carpetas existen unos métodos específicos, que para facilitarnos la vida nos sonarán mucho a los que ya estamos familiarizados con el sistema de acceso a los datos en tiempo real.

Del lado de Javascript tenemos que comenzar accediendo al servicio donde se encuentra el API de Storage.

var storageService = firebase.storage();

Una vez tenemos nuestro servicio, podemos acceder a toda la serie de funciones que se encuentran en él. El paso que generalmente realizarás a continuación es enlazar con una referencia. Puedes entender una referencia como una ruta dentro del sistema de almacenamiento, como una ruta en el sistema de base de datos o una ruta a un archivo de tu disco duro.

var referencia = storageService.ref('ruta/a/un/lugar/de/almacenamiento');

Otra alternativa sería obtener una referencia raíz y luego con el método child() navegar a una referencia interior.

var referencia = storageService.ref();
var referencia = referencia.child('images');

Subir un archivo a Storage Firebase

Subir un archivo es tan sencillo como, partiendo de una referencia, invocar el método put() que se encargará de realizar todo el trabajo por nosotros. Este método recibe dos parámetros, el propio archivo a subir y un objeto con metadatos. El parámetro de metadatos es opcional pero esencial para implementar mecanismos importantes con respecto al tratamiento de archivos.

El método nos devuelve un objeto de la clase "UploadTask" (firebase.storage.UploadTask) con el que podemos monitorizar el estado del upload del archivo mediante eventos que explicaremos en el punto siguiente de este artículo, así como realizar acciones como cancelar una subida de archivo.

var uploadTask = referencia.put(file, metadata);

Nota: La parte de obtener ese archivo ("Blob" o "File") mediante el navegador ya es otro asunto y lo puedes hacer con APIs HTML5. El API File permite acceder a archivos del disco duro del usuario, que haya seleccionado mediante un campo INPUT type file. El API Blob básicamente permite crear objetos con datos generados desde Javascript, es decir, que no necesariamente corresponden con archivos que tengas en tu disco duro. Veremos un ejemplo más tarde.

Suscribirse a eventos relacionados con la carga de archivos

Igual que hay eventos que tienen que ver con la autenticación, el SDK de Firebase implementa eventos que se disparan cuando ocurren cosas que tienen que ver con la parte de almacenamiento.

El evento "state_changed" lo podemos gestionar a partir del objeto de la clase UploadTask que hemos recibido como respuesta a una operación put(). Es el que nos permite suscribirnos a cambios de estado del proceso de upload del archivo.

Este evento se invoca con el método on() sobre el objeto de la clase UploadTask, al que se le tienen que indicar varios parámetros.

uploadTask.on('state_changed', null, function(error){
  console.log("Se ha producido un error:, ", error);
}, function() {
  console.log("Carga del archivo completada");
});

Como puedes ver, hemos enviado como función "Next" el valor null, porque no queremos monitorizar el estado de la carga durante el tiempo de carga. Luego tenemos las dos funciones para detectar posibles errores y la carga completada.

El "snapshot" de un proceso de carga

Durante el proceso de carga de un archivo, y una vez que ya ha terminado este proceso, podemos acceder a una instantánea del estado del upload o al resultado final de la carga. A partir del snapshot podemos obtener información diversa, como por ejemplo el estado actual, los bytes transferidos, o la URL donde quedó ese archivo en la nube.

El snapshot pertenece también al objeto de la clase UploadTask y podemos acceder a él de la siguiente manera. No vamos a ver todas las posibilidades ahora, pero sí algunas básicas:

Ejercicio completo de upload de un archivo a Firebase

Ahora vamos a irnos a la parte práctica y veremos un código completo que realiza las funciones de upload de un archivo. Pero antes debes saber que de manera predeterminada Firebase exige que para subir archivos deba haberse autenticado el usuario mediante cualquiera de los mecanismos. En este ejemplo usaremos autenticación anónima, pero ten en cuenta que debe estar habilitada en la consola de Firebase.

Ten en cuenta también que tendrás que colocar tus propios datos de aplicación Firebase para que funcione. Explicamos cómo obtener tus datos de inicialización de Firebase en el artículo sobre Introducción a Firebase 3.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Subir archivos con Firebase</title>
</head>
<body>
  <input type="file" id="campoarchivo">
  <div id="mensaje"></div>

  <script src="https://www.gstatic.com/firebasejs/live/3.0/firebase.js"></script>
  <script>
    // Initialize Firebase
    var config = {
      apiKey: "AIzaSyAKAAAPi-aPffdsliTggEtTW23s222I371Y",
      authDomain: "tuapp.firebaseapp.com",
      databaseURL: "https://tuapp.firebaseio.com",
      storageBucket: "tuapp.appspot.com",
    };
    firebase.initializeApp(config);

    // Servicios de APIs Firebase
    var authService = firebase.auth();
    var storageService = firebase.storage();

    window.onload = function() {
      // realizamos la autenticación anónima (debe estar activada en la consola de Firebase)
      authService.signInAnonymously()
        .catch(function(error) {
          console.error('Detectado error de autenticación', error);
        });

      // asociamos el manejador de eventos sobre el INPUT FILE
      document.getElementById('campoarchivo').addEventListener('change', function(evento){
        evento.preventDefault();
        var archivo  = evento.target.files[0];
        subirArchivo(archivo);
      });
    }

    // función que se encargará de subir el archivo
    function subirArchivo(archivo) {
      // creo una referencia al lugar donde guardaremos el archivo
      var refStorage = storageService.ref('micarpeta').child(archivo.name);
      // Comienzo la tarea de upload
      var uploadTask = refStorage.put(archivo);

      // defino un evento para saber qué pasa con ese upload iniciado
      uploadTask.on('state_changed', null,
        function(error){
          console.log('Error al subir el archivo', error);
        },
        function(){
          console.log('Subida completada');
          mensajeFinalizado(uploadTask.snapshot.downloadURL, uploadTask.snapshot.totalBytes);
        }
      );
    }

    // a esta función la invocamos para mostrar el mensaje final después del upload
    function mensajeFinalizado(url, bytes) {
      var elMensaje = document.getElementById('mensaje');
      var textoMensaje = '<p>Subido el archivo!';
      textoMensaje += '<br>Bytes subidos: ' + bytes;
      textoMensaje += '<br><a href="' + url + '">Ver el fichero</a></p>';
      elMensaje.innerHTML = textoMensaje;
    }
  </script>
</body>
</html>

Hemos comentado el código para que no te pierdas. Estamos seguros que después de la lectura del artículo y los comentarios eres capaz de identificar toda la operativa de carga de un fichero a Firebase. Si lo pruebas solo ten en cuenta colocar tus propios datos de inicialización de Firebase.

Es un script de carga simplificado lo suficiente para que sea sencillo de entender. En otros artículos lo editaremos para hacerlo un poco más sofisticado y que sea capaz de mostrarnos el progreso de una subida, algo muy importante para las cargas de archivos grandes.

Miguel Angel Alvarez

Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...

Manual