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);
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.
- El evento, "state_changed"
- La función callback "Next": que permite hacer cosas durante la carga. Es como un "observer" que se invoca repetidas veces y en el que somos capaces de obtener datos como podría ser el porcentaje de subida del archivo o el estado del upload. Si no se quiere definir ese observador se puede enviar simplemente un null.
- La función callback "Error": que es como cualquier error de Firebase y será invocada en caso que la carga del archivo falle.
- La función callback "Complete": que se invocará cuando la carga del archivo haya terminado.
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:
- uploadTask.snapshot.totalBytes: Los bytes totales del archivo a ser enviados para su carga.
- uploadTask.snapshot.bytesTransferred: Los bytes transferidos hasta un instante dado.
- uploadTask.snapshot.state: El estado actual de la subida.
- uploadTask.snapshot.downloadURL: una cadena la dirección donde está disponible ese archivo en la nube.
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...