First and main problem I had was connecting with my Google Cloud Service, this means:
- I generated a brand new private key from Firebase Admin

Downloaded file and settle on my project as my new Key.json
Then comes the trickiest part. According to Google's documentation
You can use the bucket references returned by the Admin SDK in conjunction with the official Google Cloud Storage client libraries to upload, download, and modify content in the buckets associated with your Firebase projects. Note that you do not have to authenticate Google Cloud Storage libraries when using the Firebase Admin SDK. The bucket references returned by the Admin SDK are already authenticated with the credentials used to initialize your Firebase app.
This means, if you are running you service locally (npm run shell
), you need to instantiate your firebase-admin
.
var serviceAccount = require("./key.json");
var admin = require("firebase-admin");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://<my_project>.firebaseio.com"
});
and then calling
const bucket = admin.storage().bucket('<my_bucket>.appspot.com')
you will be ready to access your files. When accessing your google functions directly through deployment or from cloud console, then accessing your storage wouldn't require an admin
initialization or the key itself such as the first exposed index.js
on the question, turning the code only into something like
const {Storage} = require('@google-cloud/storage');
...
const storage = new Storage({
projectId: '<my_id>',
});
const bucket = storage.bucket('<my_bucket>')
...
Regarding what Mayeru
said:
you have specified the directory as "/images" but instead it should be "images/"
"images/"
could be used for querying prefix
parameters, not directory
. This example shows how it works, like its reference to google's documentation as well.
The following code, with some promise tweaks and parsing JSON data for Android, works like a charm. Locally and remotely.
index.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;
}
This will for sure list all the files under images
folder from your bucket and access their signed download urls to be rendered with libraries like Fresco
. Last, but not least, the download URL will be exposed, but to make a GET
request directly on it will require adjustment on your bucket permissions. Anyway, this "permissions thing" is another topic which you might find how to do it also here on stack overflow.