5
votes

I've written the following code for my QR file upload using firebase cloud functions

const functions = require('firebase-functions');
const qrcode = require('qrcode')
const admin = require('firebase-admin');
const spawn = require('child-process-promise').spawn;
const serviceAccount = require("./secret.json");
const gcs = require('@google-cloud/storage')();

admin.initializeApp(functions.config({
  credential: admin.credential.cert(serviceAccount),
  storageBucket: "https://SECRET.firebaseio.com"
}));


exports.qrcode = functions.https.onRequest((req, res) => {
  const storage = admin.storage().bucket();
  const dummyFile = storage.file('dummy.png')
  new Promise ((resolve, reject) => qrcode.toFileStream(
    dummyFile.createWriteStream()
      .on('finish', resolve)
      .on('error', reject),
    'DummyQR'))
    .then(console.log("success")) //Doing stuff here later
    .catch(console.log)
  res.send("<script>window.close();</script>")
});

According to the docs I should be able to connect to the bucket by simply calling admin.storage().bucket(); (https://firebase.google.com/docs/storage/admin/start) however I get the following error:

Error: Error occurred while parsing your function triggers.

Error: Bucket name not specified or invalid. Specify a valid bucket name via the storageBucket option when initializing the app, or specify the bucket name explicitly when calling the getBucket() method.

and so I'm stuck and not sure how to proceed. If I try to manually enter the bucket admin.storage().bucket("https://SECRET.firebaseio.com"); I get the error

{ ApiError: Not Found
    at Object.parseHttpRespBody (/user_code/node_modules/firebase-admin/node_modules/@google-cloud/storage/node_modules/@google-cloud/common/src/util.js:193:30)
    at Object.handleResp (/user_code/node_modules/firebase-admin/node_modules/@google-cloud/storage/node_modules/@google-cloud/common/src/util.js:131:18)
    at /user_code/node_modules/firebase-admin/node_modules/@google-cloud/storage/node_modules/@google-cloud/common/src/util.js:496:12
    at Request.onResponse [as _callback] (/user_code/node_modules/firebase-admin/node_modules/retry-request/index.js:195:7)
    at Request.self.callback (/user_code/node_modules/firebase-admin/node_modules/request/request.js:185:22)
    at emitTwo (events.js:106:13)
    at Request.emit (events.js:191:7)
    at Request.<anonymous> (/user_code/node_modules/firebase-admin/node_modules/request/request.js:1157:10)
    at emitOne (events.js:96:13)
    at Request.emit (events.js:188:7)
  code: 404,
  errors: [ { domain: 'global', reason: 'notFound', message: 'Not Found' } ],
  response: undefined,
  message: 'Not Found' }
5

5 Answers

19
votes

I had this same problem. I just added the storageBucket name when initializing the app, and if you are using the getSignedUrl method you need to include a service account, otherwise that url it's gonna get expired after a week (as it was in my case).

const serviceAccount = require('/your/service/account/key/path');
admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    storageBucket: "your-storage-bucket-name.appspot.com",
});

don't forget to update your firebase functions with

firebase deploy --only functions

on the command line

UPDATE 6 APRIL 2020

Signed URLs actually expire after 7 days. If you need URLs for more time than that, you should read this answer and this thread

3
votes

It looks like you're not initializing the admin SDK correctly. Just call initializeApp with no parameters to get all the correct defaults:

admin.initializeApp();

This will use the default service account provided by Cloud Functions for your project. This account has permission to do most of what you need to do in your function without any additional configuration.

0
votes

In my case it was similar issue to this one (Unable to use cloud storage without specifying storageBucket when initialising app with firebase-admin).

I had following setup:

const admin = require("firebase-admin")
admin.initializeApp()

export * from "./api/api"
export * from "./cron/cronJobs"
export * from "./posts/postsCloudFunctions"

Changed it to:

const admin = require("firebase-admin")

export * from "./api/api"
export * from "./cron/cronJobs"
export * from "./posts/postsCloudFunctions"

admin.initializeApp()

And it seems the issue is initializeApp() was not being called before accessing the storage bucket.

0
votes

I have same issue while uploading to image to firebase storage:

Error: Bucket name not specified or invalid. Specify a valid bucket name via the storageBucket option when initializing the app, or specify the bucket name explicitly when calling the getBucket() method. ndlers\users.js:130:8) at Busboy.emit (events.js:189:13) at Busboy.emit (E:\react-project\socialape-functions\functions\node_modules\busboy\lib\main.js:37:33) at E:\react-project\socialape-functions\functions\node_modules\busboy\lib\types\multipart.js:52:13 at process._tickCallback (internal/process/next_tick.js:61:11)

Then i add storageBucket to admin function

var admin = require("firebase-admin");
var serviceAccount = require("your service account key file path);

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://your-app-1234.firebaseio.com",
  storageBucket: "your-storage-bucket-name given in firebase storage"
});

const db = admin.firestore();

module.exports = { admin, db };

After adding bucket to admin functions it works.

0
votes

You should change

storageBucket: "your-storage-bucket-name given in firebase storage"

to

storageBucket: "<BUCKET_NAME>.appspot.com".

You can find BUCKET_NAME as the picture below:

enter image description here