Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get public download link within a firebase storage trigger function: "onFinalize"?

I am writing a firebase cloud function that records the download link of a recentally uploaded file to real-time database:

exports.recordImage = functions.storage.object().onFinalize((object) => {

});

"object" gives me access to two variables "selfLink" and "mediaLink" but both of them when entered in a browser they return the following:

Anonymous caller does not have storage.objects.get access to ... {filename}

So, they are not public links. How can I get the public download link within this trigger function?

like image 326
Osama Avatar asked Nov 07 '18 12:11

Osama


People also ask

How can I get download URL from Firebase Storage?

Once you have a reference, you can download files from Cloud Storage by calling the getBytes() or getStream() . If you prefer to download the file with another library, you can get a download URL with getDownloadUrl() .

How can I get image URL from Firebase Storage?

Image URL is obtained by uploading an image to firebase bucket and then that can return back a URL that URL is a permanent URL which can be open anywhere. Then a user can use this URL for any purpose in its application.


2 Answers

You have to use the asynchronous getSignedUrl() method, see the doc of the Cloud Storage Node.js library: https://cloud.google.com/nodejs/docs/reference/storage/2.0.x/File#getSignedUrl.

So the following code should do the trick:

.....
const defaultStorage = admin.storage();
.....

exports.recordImage = functions.storage.object().onFinalize(object => {    
  const bucket = defaultStorage.bucket();
  const file = bucket.file(object.name);

  const options = {
    action: 'read',
    expires: '03-17-2025'
  };

  // Get a signed URL for the file
  return file
    .getSignedUrl(options)
    .then(results => {
      const url = results[0];

      console.log(`The signed url for ${filename} is ${url}.`);
      return true;
    })

});

Note that, in order to use the getSignedUrl() method, you need to initialize the Admin SDK with the credentials for a dedicated service account, see this SO Question & Answer firebase function get download url after successfully save image to firebase cloud storage.

like image 163
Renaud Tarnec Avatar answered Oct 12 '22 03:10

Renaud Tarnec


*use this function:

function mediaLinkToDownloadableUrl(object) {
        var firstPartUrl = object.mediaLink.split("?")[0] // 'https://www.googleapis.com/download/storage/v1/b/abcbucket.appspot.com/o/songs%2Fsong1.mp3.mp3'
        var secondPartUrl = object.mediaLink.split("?")[1] // 'generation=123445678912345&alt=media'

        firstPartUrl = firstPartUrl.replace("https://www.googleapis.com/download/storage", "https://firebasestorage.googleapis.com")
        firstPartUrl = firstPartUrl.replace("v1", "v0")

        firstPartUrl += "?" + secondPartUrl.split("&")[1]; // 'alt=media'
        firstPartUrl += "&token=" + object.metadata.firebaseStorageDownloadTokens

        return firstPartUrl
    }

this is how your code might look like:

export const onAddSong = functions.storage.object().onFinalize((object) => {

    console.log("object: ", object);

    var url = mediaLinkToDownloadableUrl(object);

    //do anything with url, like send via email or save it in your database in playlist table 
    //in my case I'm saving it in mongodb database

    return new playlistModel({
        name: storyName,
        mp3Url: url,
        ownerEmail: ownerEmail
    })
    .save() // I'm doing nothing on save complete
    .catch(e => {
        console.log(e) // log if error occur in database write
    })

})

*I have tested this method on mp3 files, I'm sure it will work on all type of files but incase if it doesnt work for you simply go to firebase storage dashboard open any file and copy download url, and try to generate the same url in your code, and edit this answer too if possible

like image 28
Inzamam Malik Avatar answered Oct 12 '22 02:10

Inzamam Malik