I have uploaded some images to firebase's storage, and then I need to show all of these images on a website. I have read the doc from firebase, but still can't find the right way to show all pictures. So, my questions are, where is my code wrong to show an even single image? How to show all images on the web at the same time (I read a post on stack overflow, it may need to get all images' URLs, so, the sub question is how to get all images' URLs)? By the way, my firebase's database is empty.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script src="https://www.gstatic.com/firebasejs/3.2.1/firebase.js"></script>
<script>
var config =
{
apiKey: "AIzaSyCKtgPuXUUqoyiwEm5sU3Blqc-A9xtBFsI",
authDomain: "cropped-images.firebaseapp.com",
databaseURL: "https://cropped-images.firebaseio.com",
storageBucket: "cropped-images.appspot.com",
};
firebase.initializeApp(config);
var storage = firebase.storage();
var storageRef = storage.ref();
var tangRef = storageRef.child('images/Tang.png');
tangRef.getDownloadURL().then(function(url)
{
var test = url
document.querySelector('img').src = test;
}).catch(function(error)
{
switch (error.code)
{
case 'storage/object_not_found':
break;
case 'storage/unauthorized':
break;
case 'storage/canceled':
break;
case 'storage/unknown':
break;
}
});
var test = 'firebase_url';
document.querySelector('img').src = test;
</script>
<img height="125" width="125"/>
</body>
</html>
And this my firebase console's storage.
Getting the download URL for a file requires a roundtrip to the Firebase servers. This call (like most of the modern internet) happens asynchronously, since blocking the browser while waiting for a response would be a bad user experience.
The easiest way to see the flow in your code is to add some logging statements:
console.log('Before requesting download URL');
tangRef.getDownloadURL().then(function(url) {
console.log('Got download URL');
});
console.log('After requesting download URL');
The console output will be:
Before requesting download URL
After requesting download URL
Got download URL
Probably not the order you expected and it means the code to set the download URL to the HTML, must be inside the then()
callback.
You're also ignoring the errors that might be raised in the catch()
callback. If you add some logging there:
tangRef.getDownloadURL().then(function(url) {
document.querySelector('img').src = url;
}).catch(function(error) {
console.error(error);
});
The code is not only a lot shorter, it actually shows precisely what the problem is:
GET https://firebasestorage.googleapis.com/v0/b/cropped-images.appspot.com/o/images%2FTang.png 403 ()
A 403 means that you don't have permission to read the image. Most likely you still have the default security rules on your Storage bucket, which means that only authenticated users can access the files. This is mentioned in the first blue note in the Firebase Storage docs for reading/writing files (emphasis mine):
Note: By default, Firebase Storage buckets require Firebase Authentication to upload files. You can change your Firebase Storage Security Rules to allow unauthenticated access. Since the default Google App Engine app and Firebase share this bucket, configuring public access may make newly uploaded App Engine files publicly accessible as well. Be sure to restrict access to your Storage bucket again when you set up authentication.
In this case, I went with the emphasized approach and added code to sign in the user (anonymously) before requesting the download URL of the image. This leads to the following complete code snippet:
var config = {
apiKey: "AIzaSyCKtgPuXUUqoyiwEm5sU3Blqc-A9xtBFsI",
authDomain: "cropped-images.firebaseapp.com",
databaseURL: "https://cropped-images.firebaseio.com",
storageBucket: "cropped-images.appspot.com",
};
firebase.initializeApp(config);
var storage = firebase.storage();
var storageRef = storage.ref();
var tangRef = storageRef.child('images/Tang.png');
// First we sign in the user anonymously
firebase.auth().signInAnonymously().then(function() {
// Once the sign in completed, we get the download URL of the image
tangRef.getDownloadURL().then(function(url) {
// Once we have the download URL, we set it to our img element
document.querySelector('img').src = url;
}).catch(function(error) {
// If anything goes wrong while getting the download URL, log the error
console.error(error);
});
});
The complete working jsbin: http://jsbin.com/kukifo/edit?html,js,console,output
Another solution than the accepted, simply change the default rules to allow users a read-only permission from the directory called images
.
service firebase.storage {
match /b/{bucket}/o {
match /images/{fileName} {
allow write: if request.auth != null;
allow read;
}
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
After this, get the download url for a file in the directory and remove the token
part.
Use
<image src="your_image_url">
Give image url to the src attribute, it will show image from firebase storage.