Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 121 Vote(s) - 3.79 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Get Download URL from file uploaded with Cloud Functions for Firebase

#1
After uploading a file in Firebase Storage with Functions for Firebase, I'd like to get the download url of the file.

I have this :

...

return bucket
.upload(fromFilePath, {destination: toFilePath})
.then((err, file) => {

// Get the download url of file

});


The object file has a lot of parameters. Even one named `mediaLink`. However, if I try to access this link, I get this error :

> Anonymous users does not have storage.objects.get access to object ...

Can somebody tell me how to get the public download Url?

Thank you
Reply

#2
Sorry but i can't post a comment to your question above because of missing reputation, so I will include it in this answer.

Do as stated above by generating a signed Url, but instead of using the service-account.json I think you have to use the serviceAccountKey.json which you can generate at (replace YOURPROJECTID accordingly)

[To see links please register here]


Example:

const gcs = require('@google-cloud/storage')({keyFilename: 'serviceAccountKey.json'});
// ...
const bucket = gcs.bucket(bucket);
// ...
return bucket.upload(tempLocalFile, {
destination: filePath,
metadata: {
contentType: 'image/jpeg'
}
})
.then((data) => {
let file = data[0]
file.getSignedUrl({
action: 'read',
expires: '03-17-2025'
}, function(err, url) {
if (err) {
console.error(err);
return;
}

// handle url
})
Reply

#3
One method I'm using with success is to set a UUID v4 value to a key named `firebaseStorageDownloadTokens` in the metadata of the file after it finishes uploading and then assemble the download URL myself following the structure Firebase uses to generate these URLs, eg:

[To see links please register here]

[BUCKET_NAME]/o/[FILE_PATH]?alt=media&token=[THE_TOKEN_YOU_CREATED]

I don't know how much "safe" is to use this method (given that Firebase could change how it generates the download URLs in the future ) but it is easy to implement.

Reply

#4
For those wondering where the Firebase Admin SDK serviceAccountKey.json file should go. Just place it in the functions folder and deploy as usual.

It still baffles me why we can't just get the download url from the metadata like we do in the Javascript SDK. Generating a url that will eventually expire and saving it in the database is not desirable.
Reply

#5
Here's an example on how to specify the download token on upload:

const UUID = require("uuid-v4");

const fbId = "<YOUR APP ID>";
const fbKeyFile = "./YOUR_AUTH_FIlE.json";
const gcs = require('@google-cloud/storage')({keyFilename: fbKeyFile});
const bucket = gcs.bucket(`${fbId}.appspot.com`);

var upload = (localFile, remoteFile) => {

let uuid = UUID();

return bucket.upload(localFile, {
destination: remoteFile,
uploadType: "media",
metadata: {
contentType: 'image/png',
metadata: {
firebaseStorageDownloadTokens: uuid
}
}
})
.then((data) => {

let file = data[0];

return Promise.resolve("https://firebasestorage.googleapis.com/v0/b/" + bucket.name + "/o/" + encodeURIComponent(file.name) + "?alt=media&token=" + uuid);
});
}

then call with

upload(localPath, remotePath).then( downloadURL => {
console.log(downloadURL);
});

The key thing here is that there is a `metadata` object nested within the `metadata` option property. Setting `firebaseStorageDownloadTokens` to a uuid-v4 value will tell Cloud Storage to use that as its public auth token.

Many thanks to @martemorfosis

Reply

#6
This works if you just need a public file with a simple URL. Note that this may overrule your Firebase storage rules.

bucket.upload(file, function(err, file) {
if (!err) {
//Make the file public
file.acl.add({
entity: 'allUsers',
role: gcs.acl.READER_ROLE
}, function(err, aclObject) {
if (!err) {
var URL = "https://storage.googleapis.com/[your bucket name]/" + file.id;
console.log(URL);
} else {
console.log("Failed to set permissions: " + err);
}
});
} else {
console.log("Upload failed: " + err);
}
});

Reply

#7
With the recent changes in the functions **object** response you can get everything you need to "stitch" together the download URL like so:

const img_url = 'https://firebasestorage.googleapis.com/v0/b/[YOUR BUCKET]/o/'
+ encodeURIComponent(object.name)
+ '?alt=media&token='
+ object.metadata.firebaseStorageDownloadTokens;

console.log('URL',img_url);

Reply

#8
I can't comment on the answer James Daniels gave, but I think this is very Important to read.

Giving out a signed URL Like he did seems for many cases pretty **bad** and possible **Dangerous**.
According to the documentation of Firebase the signed url expires after some time, so adding that to your databse will lead to a empty url after a certain timeframe

It may be that misunderstood the Documentation there and the signed url doesn't expire, which would have some security issues as a result.
The Key seems to be the same for every uploaded file. This means once you got the url of one file, someone could easily access files that he is not suposed to access, just by knowing their names.

If i missunderstood that then i would lvoe to be corrected.
Else someone should probably Update the above named solution.
If i may be wrong there
Reply

#9
For those who are using Firebase SDK and`admin.initializeApp`:

1 - [Generate a Private Key][1] and place in /functions folder.

2 - Configure your code as follows:

const serviceAccount = require('../../serviceAccountKey.json');
try { admin.initializeApp(Object.assign(functions.config().firebase, { credential: admin.credential.cert(serviceAccount) })); } catch (e) {}

[Documentation][2]

The try/catch is because I'm using a index.js that imports other files and creates one function to each file. If you're using a single index.js file with all functions, you should be ok with `admin.initializeApp(Object.assign(functions.config().firebase, { credential: admin.credential.cert(serviceAccount) }));`.

[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply

#10
I had the same issue, however, I was looking at the code of the firebase function example instead of the README. And Answers on this thread didn't help either...

You can avoid passing the config file by doing the following:

> Go to your project's [Cloud Console > IAM & admin > IAM][1], Find the App
> Engine default service account and add the Service Account Token
> Creator role to that member. This will allow your app to create signed
> public URLs to the images.

source: [Automatically Generate Thumbnails function README][2]


Your role for app engine should look like this:

[![Cloud Console][3]][3]


[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through