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

Category: Swift

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.

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.

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.

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
}

})

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)

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!