5 tips for Firebase Storage

You asked for it, and it’s finally here: file storage for Firebase developers!

Firebase Storage is a stand-alone solution for uploading user generated content like images and videos from an iOS and Android device, as well as the Web. In typical Firebase fashion, there’s no server required. Firebase Storage is designed specifically for scale, security, and network resiliency.

  • Scale: Every file uploaded is backed by Google Cloud Storage, which scales to petabytes.
  • Security: Files can be secured to specific users or sets of users using Storage Security Rules.
  • Network Resiliency: Uploads and downloads are automatically retried in the case of poor network connections, so you don’t have to keep track of them yourself.

In this blog post, we’ll cover five tips to help you go far with Firebase Storage. But enough with the chatter, let’s see some code!

Tips

1. References point to files

Even if you’re not familiar with the Realtime Database, you’ll feel right at home storing data with Firebase Storage. Firebase Storage uses a simple folder/file system to structure data. Each file is accessed through a reference:

const storageRef = firebase.storage.ref("folderName/file.jpg");
let storageRef = FIRStorage.reference().child("folderName/file.jpg")
StorageReference storageRef = FirebaseStorage.getInstance().reference().child("folderName/file.jpg");

References give you control over files at that location in your storage bucket. With this storage reference you can easily download an existing file, or upload a new one.

2. Upload files with one method

Once you have a reference, you can upload a file with one method:

var storageRef = firebase.storage.ref("folderName/file.jpg");
var fileUpload = document.getElementById("fileUpload");
fileUpload.on(‘change’, function(evt) {
  var firstFile = evt.target.file[0]; // get the first file uploaded
  var uploadTask = storageRef.put(firstFile);
});
let storageRef = FIRStorage.reference().child("folderName/file.jpg");
let localFile: NSURL = // get a file;

// Upload the file to the path "folderName/file.jpg"
let uploadTask = storageRef.putFile(localFile, metadata: nil)
StorageReference storageRef = FirebaseStorage.getInstance().reference().child("folderName/file.jpg");
Uri file = Uri.fromFile(new File("path/to/folderName/file.jpg"));
UploadTask uploadTask = storageRef.putFile(file);

For the web, the binary file comes from the File object received from the <input type="file" /> element. iOS users can upload a file from memory or from a local file. On Android you can even upload using a stream.

3. Monitor progress with Tasks

Need to create a progress indicator for your app? Firebase Storage makes it easy. When you upload or download a file, Firebase Storage creates UploadTask or DownloadTasks, which allows you to monitor the progress of the file upload or download.

const storageRef = firebase.storage.ref("folderName/file.jpg");
const fileUpload = document.getElementById("fileUpload");
fileUpload.on(‘change’, function(evt) {
  const firstFile = evt.target.file[0]; // get the first file uploaded
  const uploadTask = storageRef.put(firstFile);
  uploadTask.on(‘state_changed’, function progress(snapshot) {
     console.log(snapshot.totalBytesTransferred); // progress of upload
  });
});
let storageRef = FIRStorage.reference().child("folderName/file.jpg");
let localFile: NSURL = // get a file;

// Upload the file to the path "folderName/file.jpg"
let uploadTask = storageRef.putFile(localFile, metadata: nil)

let observer = uploadTask.observeStatus(.Progress) { snapshot in
  print(snapshot.progress) // NSProgress object
}
StorageReference storageRef = FirebaseStorage.getInstance().reference().child("folderName/file.jpg");
Uri file = Uri.fromFile(new File("path/to/images/file.jpg"));
UploadTask uploadTask = storageRef.putFile(file);
uploadTask.addOnProgressListener(new OnProgressListener() {
    @Override
    public void onProgress(UploadTask.TaskSnapshot snapshot) {
        System.out.println(snapshot.getBytesTransferred().toString());
    }
});

The progress listeners return a snapshot of the upload and the file is uploaded to the server. This snapshot gives you useful information, such as the total size of the file in bytes and how many bytes have been uploaded so far. Using this information, you can calculate the percentage uploaded and use it to update any UI control in your app.

4. Download files with one method

There are two ways to download files with Firebase Storage, using references in the SDK or a download URL. iOS and Android users can download files into memory, disk, or from a download URL. The web SDK can download files just from a download URL.

var storageRef = firebase.storage.ref("folderName/file.jpg");
storageRef.getDownloadURL().then(function(url) {
  console.log(url);
});
let storageRef = FIRStorage.reference().child("folderName/file.jpg");
storageRef.downloadURLWithCompletion { (URL, error) -> Void in
  if (error != nil) {
    // Handle any errors
  } else {
    // Get the download URL for 'images/stars.jpg'
  }
}
StorageReference storageRef = FirebaseStorage.getInstance().reference().child("folderName/file.jpg");
storageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener() {
    @Override
    public void onSuccess(Uri uri) {
        // Got the download URL for 'users/me/profile.png'
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle any errors
    }
}); 

iOS and Android apps can either store the file in memory or on disk, or use URLs to work with popular image caching libraries. Where web apps prefer having the URL due to the modern browsers powerful caching systems.

5. User based security with Storage Security Rules

Similar to the Realtime Database, Firebase Storage provides you with a set of rules that allow you to specify constraints to the size and type of files uploaded and who has access to what files. Firebase Storage integrates with Firebase Authentication, which allows you to secure files against users in your application. This is great for situations where you only want to let users upload their own profile photos, but allow anyone else to view it.

// Only a user can upload their profile picture, but anyone can view it
service firebase.storage {
  match /b/<bucket>/o {
    match /users/{userId}/profilePicture.png {
      allow read;
      allow write: if request.auth.uid == userId;
    }
  }
}

What do you think?

We’re extremely proud of everything we’ve done with Firebase Storage so far, but it’s just the beginning and we want your feedback! What are some of your useful Firebase Storage tips? What are you using Firebase Storage for? What features would help you and your apps? Leave a comment or hit us up in our Slack Team.