Get Public URL from file uploaded with firebase-admin

SaroVin picture SaroVin · Nov 2, 2017 · Viewed 13.4k times · Source

I use firebase-admin and firebase-functions to upload a file in Firebase Storage.

I have this rules in storage:

service firebase.storage {
  match /b/{bucket}/o {
    match /images {
      allow read;
      allow write: if false;
    }
  }
}

And I want get a public URL with this code:

const config = functions.config().firebase;
const firebase = admin.initializeApp(config);
const bucketRef = firebase.storage();

server.post('/upload', async (req, res) => {

  // UPLOAD FILE

  await stream.on('finish', async () => {
        const fileUrl = bucketRef
          .child(`images/${fileName}`)
          .getDownloadUrl()
          .getResult();
        return res.status(200).send(fileUrl);
      });
});

But I have this error .child is not a function. How can I get the public url of a file with firebase-admin?

Answer

Grimthorr picture Grimthorr · Nov 2, 2017

From the sample application code on the using Cloud Storage documentation, you should be able to implement the following code to obtain the public download URL after the upload is successful:

// Create a new blob in the bucket and upload the file data.
const blob = bucket.file(req.file.originalname);
const blobStream = blob.createWriteStream();

blobStream.on('finish', () => {
    // The public URL can be used to directly access the file via HTTP.
    const publicUrl = format(`https://storage.googleapis.com/${bucket.name}/${blob.name}`);
    res.status(200).send(publicUrl);
});

Alternatively, if you need a publicly accessible download URL, see this answer which suggests using getSignedUrl() from the Cloud Storage NPM module because the Admin SDK doesn't support this directly:

You'll need to generate a signed URL using getSignedURL via the @google-cloud/storage NPM module.

Example:

const gcs = require('@google-cloud/storage')({keyFilename: 'service-account.json'});
// ...
const bucket = gcs.bucket(bucket);
const file = bucket.file(fileName);
return file.getSignedUrl({
  action: 'read',
  expires: '03-09-2491'
}).then(signedUrls => {
  // signedUrls[0] contains the file's public URL
});