OregonDuck OregonDuck - 3 months ago 234
Javascript Question

How to show images in firebase storage by index.html

I have upload 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 even single image? How to show all images on web at the same time (I read 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. Thanks a lot!

<!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.

firebase console's storage

Answer

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

Comments