Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

File upload with filestreams and Firebase cloud functions + cloud storage

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' }
like image 292
Marc Avatar asked Jun 07 '18 15:06

Marc


2 Answers

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

like image 65
ihojmanb Avatar answered Oct 31 '22 14:10

ihojmanb


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.

like image 41
Doug Stevenson Avatar answered Oct 31 '22 13:10

Doug Stevenson