Estoy trabajando en subir imágenes, todo funciona muy bien, pero tengo 100 imágenes y me gustaría mostrarlas todas en mi View
, ya que obtengo la lista completa de las imágenes en una carpeta, no encuentro ninguna API para esto trabajo.
Estoy trabajando en subir imágenes, todo funciona muy bien, pero tengo 100 imágenes y me gustaría mostrarlas todas en mi View
, ya que obtengo la lista completa de las imágenes en una carpeta, no encuentro ninguna API para esto trabajo.
Respuestas:
Desde la versión 6.1 de Firebase SDK para JavaScript , la versión 6.4 de iOS y la versión 18.1 de Android tienen un método para enumerar archivos.
La documentación es un poco escasa hasta ahora, por lo que recomiendo consultar la respuesta de Rosário para obtener más detalles.
Respuesta anterior, ya que este enfoque todavía puede ser útil a veces:
Actualmente, no hay una llamada a la API en el SDK de Firebase para enumerar todos los archivos en una carpeta de Cloud Storage desde una aplicación. Si necesita dicha funcionalidad, debe almacenar los metadatos de los archivos (como las URL de descarga) en un lugar donde pueda enumerarlos. La base de datos en tiempo real Firebase y Nube Firestore son perfectos para esto y le permite compartir fácilmente también las direcciones URL con los demás.
Puede encontrar una buena (pero algo complicada) muestra de esto en nuestra aplicación de muestra FriendlyPix . El código relevante para la versión web está aquí , pero también hay versiones para iOS y Android.
A partir de mayo de 2019, la versión 6.1.0 del SDK de Firebase para Cloud Storage ahora admite la lista de todos los objetos de un depósito. Simplemente necesita llamar listAll()
a Reference
:
// Since you mentioned your images are in a folder,
// we'll create a Reference to that folder:
var storageRef = firebase.storage().ref("your_folder");
// Now we get the references of these images
storageRef.listAll().then(function(result) {
result.items.forEach(function(imageRef) {
// And finally display them
displayImage(imageRef);
});
}).catch(function(error) {
// Handle any errors
});
function displayImage(imageRef) {
imageRef.getDownloadURL().then(function(url) {
// TODO: Display the image on the UI
}).catch(function(error) {
// Handle any errors
});
}
Tenga en cuenta que para usar esta función, debe optar por la versión 2 de las Reglas de seguridad , lo que se puede hacer haciendo rules_version = '2';
la primera línea de sus reglas de seguridad:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
Recomiendo consultar los documentos para obtener más referencias.
Además, de acuerdo con la configuración , en el Paso 5, este script no está permitido Node.js
ya require("firebase/app");
que no regresará firebase.storage()
como una función. Esto solo se logra usando import * as firebase from 'firebase/app';
.
Desde marzo de 2017: con la incorporación de Firebase Cloud Functions y la integración más profunda de Firebase con Google Cloud, esto ahora es posible.
Con Cloud Functions puedes usar el paquete Google Cloud Node para hacer épicas operaciones en Cloud Storage. A continuación, se muestra un ejemplo que obtiene todas las URL de archivo en una matriz desde Cloud Storage. Esta función se activará cada vez que se guarde algo en el almacenamiento en la nube de Google.
Nota 1 : Esta es una operación bastante costosa desde el punto de vista computacional, ya que tiene que recorrer todos los archivos en un depósito / carpeta.
Nota 2 : escribí esto solo como un ejemplo, sin poner muchos detalles en las promesas, etc. Solo para dar una idea.
const functions = require('firebase-functions');
const gcs = require('@google-cloud/storage')();
// let's trigger this function with a file upload to google cloud storage
exports.fileUploaded = functions.storage.object().onChange(event => {
const object = event.data; // the object that was just uploaded
const bucket = gcs.bucket(object.bucket);
const signedUrlConfig = { action: 'read', expires: '03-17-2025' }; // this is a signed url configuration object
var fileURLs = []; // array to hold all file urls
// this is just for the sake of this example. Ideally you should get the path from the object that is uploaded :)
const folderPath = "a/path/you/want/its/folder/size/calculated";
bucket.getFiles({ prefix: folderPath }, function(err, files) {
// files = array of file objects
// not the contents of these files, we're not downloading the files.
files.forEach(function(file) {
file.getSignedUrl(signedUrlConfig, function(err, fileURL) {
console.log(fileURL);
fileURLs.push(fileURL);
});
});
});
});
Espero que esto les dé una idea general. Para obtener mejores ejemplos de funciones en la nube, consulte el repositorio de Github de Google lleno de muestras de Cloud Functions para Firebase . Consulte también la documentación de la API de Google Cloud Node
.then
como esta:this.bucket .getFiles({ prefix: 'path/to/directory' }) .then((arr) => {})
Como no hay ningún idioma en la lista, responderé esto en Swift. Recomendamos encarecidamente usar Firebase Storage y Firebase Realtime Database juntos para lograr listas de descargas:
Compartido:
// Firebase services
var database: FIRDatabase!
var storage: FIRStorage!
...
// Initialize Database, Auth, Storage
database = FIRDatabase.database()
storage = FIRStorage.storage()
...
// Initialize an array for your pictures
var picArray: [UIImage]()
Subir:
let fileData = NSData() // get data...
let storageRef = storage.reference().child("myFiles/myFile")
storageRef.putData(fileData).observeStatus(.Success) { (snapshot) in
// When the image has successfully uploaded, we get it's download URL
let downloadURL = snapshot.metadata?.downloadURL()?.absoluteString
// Write the download URL to the Realtime Database
let dbRef = database.reference().child("myFiles/myFile")
dbRef.setValue(downloadURL)
}
Descargar:
let dbRef = database.reference().child("myFiles")
dbRef.observeEventType(.ChildAdded, withBlock: { (snapshot) in
// Get download URL from snapshot
let downloadURL = snapshot.value() as! String
// Create a storage reference from the URL
let storageRef = storage.referenceFromURL(downloadURL)
// Download the data, assuming a max size of 1MB (you can change this as necessary)
storageRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in
// Create a UIImage, add it to the array
let pic = UIImage(data: data)
picArray.append(pic)
})
})
Para obtener más información, consulte Zero to App: Develop with Firebase , y su código fuente asociado , para ver un ejemplo práctico de cómo hacer esto.
Una solución puede ser crear un archivo (es decir, list.txt) sin nada dentro, en este archivo puede configurar los metadatos personalizados (es decir, un Mapa <Cadena, Cadena>) con la lista de todas las URL del archivo.
Entonces, si necesita descargar todos los archivos en un fodler, primero descargue los metadatos del archivo list.txt, luego recorra los datos personalizados y descargue todos los archivos con las URL en el mapa.
También encontré este problema cuando estaba trabajando en mi proyecto. Realmente deseo que proporcionen un método de API final. De todos modos, así es como lo hice: cuando esté cargando una imagen en el almacenamiento de Firebase, cree un Objeto y páselo a la base de datos de Firebase al mismo tiempo. Este objeto contiene el URI de descarga de la imagen.
trailsRef.putFile(file).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Uri downloadUri = taskSnapshot.getDownloadUrl();
DatabaseReference myRef = database.getReference().child("trails").child(trail.getUnique_id()).push();
Image img = new Image(trail.getUnique_id(), downloadUri.toString());
myRef.setValue(img);
}
});
Más tarde, cuando desee descargar imágenes de una carpeta, simplemente recorra los archivos de esa carpeta. Esta carpeta tiene el mismo nombre que la "carpeta" en el almacenamiento de Firebase, pero puede asignarles el nombre que desee. Los pongo en hilo separado.
@Override
protected List<Image> doInBackground(Trail... params) {
String trialId = params[0].getUnique_id();
mDatabase = FirebaseDatabase.getInstance().getReference();
mDatabase.child("trails").child(trialId).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
images = new ArrayList<>();
Iterator<DataSnapshot> iter = dataSnapshot.getChildren().iterator();
while (iter.hasNext()) {
Image img = iter.next().getValue(Image.class);
images.add(img);
}
isFinished = true;
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
Ahora que tengo una lista de objetos que contienen los URI de cada imagen, puedo hacer lo que quiera con ellos. Para cargarlos en imageView, creé otro hilo.
@Override
protected List<Bitmap> doInBackground(List<Image>... params) {
List<Bitmap> bitmaps = new ArrayList<>();
for (int i = 0; i < params[0].size(); i++) {
try {
URL url = new URL(params[0].get(i).getImgUrl());
Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
bitmaps.add(bmp);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return bitmaps;
}
Esto devuelve una lista de Bitmap, cuando termina, simplemente los adjunto a ImageView en la actividad principal. Los métodos siguientes son @Override porque he creado interfaces y escucho la finalización en otros hilos.
@Override
public void processFinishForBitmap(List<Bitmap> bitmaps) {
List<ImageView> imageViews = new ArrayList<>();
View v;
for (int i = 0; i < bitmaps.size(); i++) {
v = mInflater.inflate(R.layout.gallery_item, mGallery, false);
imageViews.add((ImageView) v.findViewById(R.id.id_index_gallery_item_image));
imageViews.get(i).setImageBitmap(bitmaps.get(i));
mGallery.addView(v);
}
}
Tenga en cuenta que primero tengo que esperar a que se devuelva List Image y luego llamar al hilo para que funcione en List Bitmap. En este caso, Image contiene el URI.
@Override
public void processFinish(List<Image> results) {
Log.e(TAG, "get back " + results.size());
LoadImageFromUrlTask loadImageFromUrlTask = new LoadImageFromUrlTask();
loadImageFromUrlTask.delegate = this;
loadImageFromUrlTask.execute(results);
}
Ojalá alguien lo encuentre útil. También servirá como una línea de gremio para mí en el futuro.
Una forma más de agregar la imagen a la base de datos mediante la función de nube para realizar un seguimiento de cada imagen cargada y almacenarla en la base de datos.
exports.fileUploaded = functions.storage.object().onChange(event => {
const object = event.data; // the object that was just uploaded
const contentType = event.data.contentType; // This is the image Mimme type\
// Exit if this is triggered on a file that is not an image.
if (!contentType.startsWith('image/')) {
console.log('This is not an image.');
return null;
}
// Get the Signed URLs for the thumbnail and original image.
const config = {
action: 'read',
expires: '03-01-2500'
};
const bucket = gcs.bucket(event.data.bucket);
const filePath = event.data.name;
const file = bucket.file(filePath);
file.getSignedUrl(config, function(err, fileURL) {
console.log(fileURL);
admin.database().ref('images').push({
src: fileURL
});
});
});
Código completo aquí: https://gist.github.com/bossly/fb03686f2cb1699c2717a0359880cf84
Para el nodo js, usé este código
const Storage = require('@google-cloud/storage');
const storage = new Storage({projectId: 'PROJECT_ID', keyFilename: 'D:\\keyFileName.json'});
const bucket = storage.bucket('project.appspot.com'); //gs://project.appspot.com
bucket.getFiles().then(results => {
const files = results[0];
console.log('Total files:', files.length);
files.forEach(file => {
file.download({destination: `D:\\${file}`}).catch(error => console.log('Error: ', error))
});
}).catch(err => {
console.error('ERROR:', err);
});
Puede enumerar archivos en un directorio de almacenamiento de base de fuego mediante el método listAll (). Para utilizar este método, debe implementar esta versión de firebase storage. 'com.google.firebase: firebase-storage: 18.1.1'
https://firebase.google.com/docs/storage/android/list-files
Tenga en cuenta que actualice las Reglas de seguridad a la versión 2.
En realidad, esto es posible, pero solo con una API de Google Cloud en lugar de una de Firebase. Esto se debe a que un almacenamiento de Firebase es un depósito de almacenamiento de Google Cloud al que se puede acceder fácilmente con las API de Google Cloud, sin embargo, debe usar OAuth para la autenticación en lugar del de Firebase.
Enfrenté el mismo problema, el mío es aún más complicado.
El administrador cargará archivos de audio y pdf en el almacenamiento:
audios / season1, season2 ... / class1, class 2 / archivos .mp3
libros / archivos .pdf
La aplicación de Android necesita obtener la lista de subcarpetas y archivos.
La solución es capturar el evento de carga en el almacenamiento y crear la misma estructura en firestore utilizando la función de nube.
Paso 1: Cree manualmente una colección de 'almacenamiento' y un documento de 'audios / libros' en firestore
Paso 2: configurar la función de nube
Puede tardar unos 15 minutos: https://www.youtube.com/watch?v=DYfP-UIKxH0&list=PLl-K7zZEsYLkPZHe41m4jfAxUi0JjLgSM&index=1
Paso 3: captura el evento de carga usando la función de nube
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp(functions.config().firebase);
const path = require('path');
export const onFileUpload = functions.storage.object().onFinalize(async (object) => {
let filePath = object.name; // File path in the bucket.
const contentType = object.contentType; // File content type.
const metageneration = object.metageneration; // Number of times metadata has been generated. New objects have a value of 1.
if (metageneration !== "1") return;
// Get the file name.
const fileName = path.basename(filePath);
filePath = filePath.substring(0, filePath.length - 1);
console.log('contentType ' + contentType);
console.log('fileName ' + fileName);
console.log('filePath ' + filePath);
console.log('path.dirname(filePath) ' + path.dirname(filePath));
filePath = path.dirname(filePath);
const pathArray = filePath.split("/");
let ref = '';
for (const item of pathArray) {
if (ref.length === 0) {
ref = item;
}
else {
ref = ref.concat('/sub/').concat(item);
}
}
ref = 'storage/'.concat(ref).concat('/sub')
admin.firestore().collection(ref).doc(fileName).create({})
.then(result => {console.log('onFileUpload:updated')})
.catch(error => {
console.log(error);
});
});
Paso 4: recupere la lista de carpetas / archivos en la aplicación de Android usando firestore
private static final String STORAGE_DOC = "storage/";
public static void getMediaCollection(String path, OnCompleteListener onCompleteListener) {
String[] pathArray = path.split("/");
String doc = null;
for (String item : pathArray) {
if (TextUtils.isEmpty(doc)) doc = STORAGE_DOC.concat(item);
else doc = doc.concat("/sub/").concat(item);
}
doc = doc.concat("/sub");
getFirestore().collection(doc).get().addOnCompleteListener(onCompleteListener);
}
Paso 5: obtener la URL de descarga
public static void downloadMediaFile(String path, OnCompleteListener<Uri> onCompleteListener) {
getStorage().getReference().child(path).getDownloadUrl().addOnCompleteListener(onCompleteListener);
}
Nota
Tenemos que poner una colección "sub" a cada elemento ya que firestore no admite recuperar la lista de colecciones.
Me tomó 3 días encontrar la solución, con suerte te llevará 3 horas como máximo.
Salud.
Ampliando la respuesta de Rosário Pereira Fernandes , para una solución de JavaScript:
npm install -g firebase-tools
JavaScript
como idioma predeterminado npm install --save firebase
npm install @google-cloud/storage
npm install @google-cloud/firestore
... <any other dependency needed>
"firebase": "^6.3.3",
"@google-cloud/storage": "^3.0.3"
funciones / package.json
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "10"
},
"dependencies": {
"@google-cloud/storage": "^3.0.3",
"firebase": "^6.3.3",
"firebase-admin": "^8.0.0",
"firebase-functions": "^3.1.0"
},
"devDependencies": {
"eslint": "^5.12.0",
"eslint-plugin-promise": "^4.0.1",
"firebase-functions-test": "^0.1.6"
},
"private": true
}
listAll
funciónindex.js
var serviceAccount = require("./key.json");
const functions = require('firebase-functions');
const images = require('./images.js');
var admin = require("firebase-admin");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://<my_project>.firebaseio.com"
});
const bucket = admin.storage().bucket('<my_bucket>.appspot.com')
exports.getImages = functions.https.onRequest((request, response) => {
images.getImages(bucket)
.then(urls => response.status(200).send({ data: { urls } }))
.catch(err => console.error(err));
})
images.js
module.exports = {
getImages
}
const query = {
directory: 'images'
};
function getImages(bucket) {
return bucket.getFiles(query)
.then(response => getUrls(response))
.catch(err => console.error(err));
}
function getUrls(response) {
const promises = []
response.forEach( files => {
files.forEach (file => {
promises.push(getSignedUrl(file));
});
});
return Promise.all(promises).then(result => getParsedUrls(result));
}
function getSignedUrl(file) {
return file.getSignedUrl({
action: 'read',
expires: '09-01-2019'
})
}
function getParsedUrls(result) {
return JSON.stringify(result.map(mediaLink => createMedia(mediaLink)));
}
function createMedia(mediaLink) {
const reference = {};
reference.mediaLink = mediaLink[0];
return reference;
}
firebase deploy
para cargar su función en la nubebuild.gradle
dependencies {
...
implementation 'com.google.firebase:firebase-functions:18.1.0'
...
}
clase kotlin
private val functions = FirebaseFunctions.getInstance()
val cloudFunction = functions.getHttpsCallable("getImages")
cloudFunction.call().addOnSuccessListener {...}
Con respecto al desarrollo posterior de esta función, encontré algunos problemas que podrían encontrarse aquí .
Para hacer esto con JS
Puede agregarlos directamente a su contenedor div, o puede enviarlos a una matriz. A continuación, se muestra cómo agregarlos a su div.
1) Cuando almacene sus imágenes en el almacenamiento, cree una referencia a la imagen en su base de datos de base de fuego con la siguiente estructura
/images/(imageName){
description: "" ,
imageSrc : (imageSource)
}
2) Cuando cargue su documento, extraiga todas las URL de origen de la imagen de la base de datos en lugar del almacenamiento con el siguiente código
$(document).ready(function(){
var query = firebase.database().ref('images/').orderByKey();
query.once("value").then(function(snapshot){
snapshot.forEach(function(childSnapshot){
var imageName = childSnapshot.key;
var childData = childSnapshot.val();
var imageSource = childData.url;
$('#imageGallery').append("<div><img src='"+imageSource+"'/></div>");
})
})
});
Puede utilizar el siguiente código. Aquí estoy cargando la imagen en el almacenamiento de Firebase y luego estoy almacenando la URL de descarga de la imagen en la base de datos de Firebase.
//getting the storage reference
StorageReference sRef = storageReference.child(Constants.STORAGE_PATH_UPLOADS + System.currentTimeMillis() + "." + getFileExtension(filePath));
//adding the file to reference
sRef.putFile(filePath)
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
//dismissing the progress dialog
progressDialog.dismiss();
//displaying success toast
Toast.makeText(getApplicationContext(), "File Uploaded ", Toast.LENGTH_LONG).show();
//creating the upload object to store uploaded image details
Upload upload = new Upload(editTextName.getText().toString().trim(), taskSnapshot.getDownloadUrl().toString());
//adding an upload to firebase database
String uploadId = mDatabase.push().getKey();
mDatabase.child(uploadId).setValue(upload);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) {
progressDialog.dismiss();
Toast.makeText(getApplicationContext(), exception.getMessage(), Toast.LENGTH_LONG).show();
}
})
.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
@Override
public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
//displaying the upload progress
double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount();
progressDialog.setMessage("Uploaded " + ((int) progress) + "%...");
}
});
Ahora, para obtener todas las imágenes almacenadas en la base de datos de firebase, puede usar
//adding an event listener to fetch values
mDatabase.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
//dismissing the progress dialog
progressDialog.dismiss();
//iterating through all the values in database
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
Upload upload = postSnapshot.getValue(Upload.class);
uploads.add(upload);
}
//creating adapter
adapter = new MyAdapter(getApplicationContext(), uploads);
//adding adapter to recyclerview
recyclerView.setAdapter(adapter);
}
@Override
public void onCancelled(DatabaseError databaseError) {
progressDialog.dismiss();
}
});
Para obtener más detalles, puede ver mi publicación Ejemplo de almacenamiento de Firebase .
Entonces, tenía un proyecto que requería descargar activos del almacenamiento de base de fuego, así que tuve que resolver este problema yo mismo. Aquí es cómo :
1- Primero, haga un modelo de datos por ejemplo class Choice{}
, en esa clase define una variable de cadena llamada Nombre de imagen para que sea así
class Choice {
.....
String imageName;
}
2- desde una base de datos / base de datos de fuego, vaya y codifique los nombres de las imágenes a los objetos, por lo que si tiene un nombre de imagen llamado Apple.png, cree el objeto que se
Choice myChoice = new Choice(...,....,"Apple.png");
3- Ahora, obtenga el enlace para los activos en su almacenamiento de base de fuego, que será algo así
gs://your-project-name.appspot.com/
4- finalmente, inicialice su referencia de almacenamiento de base de fuego y comience a obtener los archivos mediante un bucle como ese
storageRef = storage.getReferenceFromUrl(firebaseRefURL).child(imagePath);
File localFile = File.createTempFile("images", "png");
storageRef.getFile(localFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
@Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
//Dismiss Progress Dialog\\
}
5- eso es todo
#In Python
import firebase_admin
from firebase_admin import credentials
from firebase_admin import storage
import datetime
import urllib.request
def image_download(url, name_img) :
urllib.request.urlretrieve(url, name_img)
cred = credentials.Certificate("credentials.json")
# Initialize the app with a service account, granting admin privileges
app = firebase_admin.initialize_app(cred, {
'storageBucket': 'YOURSTORAGEBUCKETNAME.appspot.com',
})
url_img = "gs://YOURSTORAGEBUCKETNAME.appspot.com/"
bucket_1 = storage.bucket(app=app)
image_urls = []
for blob in bucket_1.list_blobs():
name = str(blob.name)
#print(name)
blob_img = bucket_1.blob(name)
X_url = blob_img.generate_signed_url(datetime.timedelta(seconds = 300), method='GET')
#print(X_url)
image_urls.append(X_url)
PATH = ['Where you want to save the image']
for path in PATH:
i = 1
for url in image_urls:
name_img = str(path + "image"+str(i)+".jpg")
image_download(url, name_img)
i+=1
Estoy usando AngularFire
y utilizo lo siguiente para obtener todos losdownloadURL
getPhotos(id: string): Observable<string[]> {
const ref = this.storage.ref(`photos/${id}`)
return ref.listAll().pipe(switchMap(list => {
const calls: Promise<string>[] = [];
list.items.forEach(item => calls.push(item.getDownloadURL()))
return Promise.all(calls)
}));
}
Para Android, la mejor práctica es usar FirebaseUI y Glide.
Debe agregar eso en su gradle / aplicación para obtener la biblioteca. ¡Tenga en cuenta que ya tiene Glide!
implementation 'com.firebaseui:firebase-ui-storage:4.1.0'
Y luego en tu código usa
// Reference to an image file in Cloud Storage
StorageReference storageReference = FirebaseStorage.getInstance().getReference();
// ImageView in your Activity
ImageView imageView = findViewById(R.id.imageView);
// Download directly from StorageReference using Glide
// (See MyAppGlideModule for Loader registration)
GlideApp.with(this /* context */)
.load(storageReference)
.into(imageView);