2

I'd like my firebase web app to upload a file, and I'd like to have a cloud function that discovers this file and creates a database object based on its contents. Here's the last variant of many I've tried...

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const { Storage } = require('@google-cloud/storage');

admin.initializeApp();
const db = admin.firestore();

exports.onStorageFinalize = functions.storage.object().onFinalize((object) => {
  const storage = new Storage();
  const bucket = storage.bucket('my app's storage bucket name');

  return bucket.file(object.name).download(function (err, contents) {
    // problem: no err, no contents, set doesn't run just a warning about promises!
    const result = `got err=${err}, contents=${contents}`
    return db.collection('myCollection').doc().set({
      result: result
    })
  });
});

The very small file is uploaded, and this trigger runs. When I don't attempt getting the contents of the file, the database object is created fine (with a literal string instead of the file result).

But when I run it as shown above, first I get a warning that says:

onStorageFinalize: Function returned undefined, expected Promise or value

That's wrong. The doc for file().download() says it returns a promise.... and, more importantly, the database set() doesn't run.

I am astounded by how confusing and obscure (and I think wrong?) the google docs are on this seemingly mainstream use case. Much obliged if someone can help.

1 Answer 1

6

As you will see in the documentation of the Google Cloud Storage Node.js Client for the File object, you have to omit the callback in order for the download() method to return a Promise.

The way you call the download() method you are not returning a promise, hence the error you receive.

So you need to do as follows:

return bucket.file(object.name).download()
    .then(data => {
        const contents = data[0];
        // Do something with the contents constant, e.g. derive the value you want to write to Firestore

        return db.collection('myCollection').doc().set({
           value: ......
        });

    });
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. Looks like your answer sends a callback, too? The arrow function? But will try it now... appreciate it.
Sorry there is an error in my answer, I forgot the then(). I gonna adapt it.
I see the link you provided (very helpful), but I am trying to understand the param sent to the promise contents = data[0]; what is data, what is the "blob" in data[0], and how can I see the plain text from my file?
I sure appreciate your help!! I found a doc for blobs and used data[0].toString()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.