Firebase Storage - How to download files using Firebase 3 SDK with Swift 3 in Xcode 8

Category: Swift
Firebase Storage - How to download files using Firebase 3 SDK with Swift 3 in Xcode 8

In order to download images or any files from the Firebase storage using URLSession dataTask you will have to get the download URL using Firebase 3 SDK method downloadURLWithCompletion.

Lately I’ve been using Firebase a lot and the one thing I didn’t like about the tutorials available out there is the wrong way of downloading images from Firebase Storage.

Most of the articles just throw a code at you where they use URLSession and start a download task. To make it work you will also need to provide a download URL of your image or any file to get it from Firebase Storage. And this is where they fail. Getting a download URL is the most important part. Why would we waste your time when Google’s team has already done this for us?

NOTE: If you haven’t installed Firebase SDK to your project or if you are missing Firebase Storage, please check out my article: Getting Started With CocoaPods – Install Your First Dependency: Firebase 3.

Let’s imagine that we are building a simple blog application where each article has a title, a description and an image. Most likely you are going to store an image name inside each item’s node in Firebase database and the image will be placed in the storage. How will you grab it?

I’d like to note that I never liked reading documentation. Ever! Most of the time they were hard to understand or there was not enough explanation. But it’s not the case with Firebase. If you simply go to Firebase docs -> iOS Section -> Download Files you will find a very explicit implementation of generating a download URL of the item in the storage.

In order to get a download url of a file first you should create a reference to your Firebase storage.

Make Firebase available in your controller by importing it: import Firebase.

To establish reference we use FIRStorage.storage().reference(forURL: "HERE_GOES_YOUR_URL"). The url you have to provide can be easily found in the Storage section in the Firebase Console.

Get Firebase Storage URL in Console

In my case the URL looks like this: FIRStorage.storage().reference(forURL: "gs://fir-blog-b00c1.appspot.com")

Firebase treats the hierarchy of items as child. In order to get an image from the root directory of storage you should call a method child on the storage instance.

So to make it more clear, if an image is called firstBlogImage.jpg the actual URL will be gs://fir-blog-b00c1.appspot.com/firstBlogImage.jpg. If you have this image inside some folder for ex.: blogimages then the url would be gs://fir-blog-b00c1.appspot.com/blogimages/firstBlogImage.jpg and so on. It’s fairly simple.

As far as you have established a reference to your storage you can simply do the following:

let storage = FIRStorage.storage().reference(forURL: "gs://fir-blog-b00c1.appspot.com")
let imageName = “firstBlogImage.jpg”
let imageURL = storage.child(imageName)

Using this code you have generated an address to your image. But don’t be fooled. It’s just an address for Firebase. You won’t be able to download image though this URL. Firebase has a lot of things going on inside so now we need to generate a download URL. Yes, the file path (or image URL) differs from the download URL that can be used later.

To get the download URL for a file by calling the downloadURLWithCompletion: method on a storage reference.

In the previous section we placed the file path to our image inside the imageURL constant. Now we will use downloadURL. Then check for errors and if there are no errors implement URLSession to actually download the image.

imageURL.downloadURL(completion: { (url, error) in
            
   if error != nil {
     print(error?.localizedDescription)
     return
    }
            
     //Now you can start downloading the image or any file from the storage using URLSession.
            
})

As you may have already guessed the steps to generate a download URL are very simple. If the downloadURLWithCompletion: method runs without any errors you will be given the url variable that will contain the shareable/downloadable URL of your file, in this case it’s an image.

Here’s the full code of getting download URL of your file and then implementation of URLSession to download the image. One thing I’d like to mention is that as far as I’m aware URLSession takes place in the background thread by default so when the download process has finished you should move the data to the main thread to display the image in the UIImageView.

let imageName = "some_image_name.jpg"
let imageURL = FIRStorage.storage().reference(forURL: "gs://fir-blog-b00c1.appspot.com").child(imageName)
        
imageURL.downloadURL(completion: { (url, error) in
            
   if error != nil {
      print(error?.localizedDescription)
      return
   }
            
   URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
                
      if error != nil {
      print(error)
      return
      }
                
      guard let imageData = UIImage(data: data!) else { return }
                
         DispatchQueue.main.async {
            self.imageView.image = imageData
         }
                
    }).resume()
            
})

One more thing to note here is that URLSession.shared.dataTask will return data variable with the actual image data. In most cases when assigning an image from the assets folder to an UIImageView we use UIImage(named: “some_image_name.jpg”). As far as the returned value is data we will use a different method let imageData = UIImage(data: data!).

Conclusion

That’s it! Next article will be dedicated to caching the downloaded images so that the same images don’t get downloaded several times as the user scrolls the page. I believe that it’s always good to do the implementation as it’s described by the developer in order to get the most out of the SDK. Hopefully this will be helpful for you and just in case something is still left unclear please let me know! Cheers!