Firebase Storage – Upload, Download, and Delete
In this tutorial, we are going to teach you, how you can upload, download and delete files from Firebase Storage. Firebase Storage is a service provided by Google that allows you to save files on their server. The free plan allows you to upload data up to 1 GB. More data can be bought from the Firebase Pricing page.
What you are going to learn:
- Upload files on Firebase Storage.
- Save the data in Realtime Database.
- Fetch files from the Firebase Storage.
- Download files from Firebase Storage.
- Fix CORS issue if working in localhost.
- Install gsutil.
- Delete files from Firebase Storage.
Video tutorial:
Upload file
We are going to upload the file to the Firebase storage and save its path in Firebase Realtime Database. It is another service provided by Google to save data in JSON format. To upload the file, we are going to show a form with an input type file that allows the user to select any type of file. We will be using Vue JS to render the HTML to view the data in real-time, for example, newly uploaded files will be displayed automatically and deleted files will be removed from the view without having to refresh the page.
<div id="app">
<form id="upload-form">
<input type="file" name="file" required />
<input type="submit" value="Upload" />
</form>
[show all uploaded here]
</div>
<script src="vue.min.js"></script>
This will display a form with an input type file to upload a file. And a submit button which when clicked will submit the form. Vue JS production file can be downloaded from here. Now you need to attach a submit event listener to this form using Javascript.
<script type="module">
// [initialize firebase here]
window.addEventListener("load", function () {
document.getElementById("upload-form").addEventListener("submit", function () {
event.preventDefault();
var form = event.target;
var file = form.file.files[0];
console.log(file);
// [upload in storage here]
});
});
</script>
If you select the file and hit submit, you will see your selected file object in the browser console. Now you need to do 2 things; initialize firebase, and upload the file. To initialize firebase, you need to create an app at Firebase Console.
- Add new project.
- Enter name of project.
- When project is created, select “web”.
- Copy the firebaseConfig variable.
Replace the [initialize firebase here] section with the following:
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.1.0/firebase-app.js";
import { getStorage, ref as stRef, uploadBytes } from "https://www.gstatic.com/firebasejs/9.1.0/firebase-storage.js";
import { getDatabase, ref as dbRef, push, set } from "https://www.gstatic.com/firebasejs/9.1.0/firebase-database.js";
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "",
authDomain: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: ""
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
// Get a reference to the storage service, which is used to create references in your storage bucket
const storage = getStorage(app);
const database = getDatabase();
const databaseReference = dbRef(database, "files");
Replace the firebaseConfig variable with your firebase configurations. Now replace the [upload in storage here] section with the following:
const storageRef = stRef(storage, "files/" + file.name);
uploadBytes(storageRef, file).then(function (snapshot) {
var newFileRef = push(databaseReference);
set(newFileRef, {
"name": file.name
});
});
This will upload the file in Firebase Storage in a folder named “files”. You can see it in your project’s dashboard in left menu in “Storage” page. Also, it will create a new element in “files” array in “Realtime Database” page.
Displaying Uploaded Files in Firebase Storage
Now the file is being uploaded in Firebase Storage and it’s path is also being saved in realtime database. Now you need to show all uploaded files. Replace the [show all uploaded here] section with the following:
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>File</th>
<th>Actions</th>
</tr>
<tr v-for="file in files">
<td>{{ file.id }}</td>
<td>{{ file.name }}</td>
<td>
[download link here]
</td>
<td>
[delete button here]
</td>
</tr>
</table>
This will create a simple HTML table. Now you need to do the following things:
- Initialize Vue JS.
- Get all data from realtime database.
- Render in HTML table.
You can initialize the Vue JS from the following code:
var vueApp = new Vue({
el: "#app",
data: {
files: []
},
// [updated event goes here]
});
Then include “onValue” in your “firebase-database” import. So your firebase database import line will become:
import { getDatabase, ref as dbRef, push, set, onValue } from "https://www.gstatic.com/firebasejs/9.1.0/firebase-database.js";
Note the “onValue” in the import block. Similarly, add the “getDownloadURL” in the import of “firebase-storage”. So your firebase storage import line will become:
import { getStorage, ref as stRef, uploadBytes, getDownloadURL } from "https://www.gstatic.com/firebasejs/9.1.0/firebase-storage.js";
Note the “getDownloadURL” in the import block. Then write the following code in your Javascript:
onValue(databaseReference, function (snapshot) {
snapshot.forEach(function (childSnapshot) {
const value = childSnapshot.val();
const storageRefDownload = stRef(storage, "files/" + value.name);
getDownloadURL(storageRefDownload).then(function (url) {
vueApp.files.push({
"id": childSnapshot.key,
"name": value.name,
"url": url
});
});
});
});
You can apply the following CSS styles to make the table look a little nice:
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 25px;
}
</style>
Download File from Firebase Storage
Now you need to download the file. First, you need to replace the [download link here] section with the following:
<a v-bind:href="file.url" v-bind:download="file.name" onclick="downloadFile();">Download</a>
Create the following function in your Javascript:
function downloadFile() {
// prevent default href action
event.preventDefault();
// get URL from href
var anchor = event.target;
var url = anchor.getAttribute("href");
// get blob data
const xhr = new XMLHttpRequest();
xhr.responseType = "blob";
xhr.onload = function (event) {
const blob = xhr.response;
// get clickable URL of blob data
const blogUrl = window.URL.createObjectURL(blob);
// replace href with new blob value
anchor.setAttribute("href", blogUrl);
// remove the onclick listener
anchor.removeAttribute("onclick");
// download the file
anchor.click();
// free up the memory
window.URL.revokeObjectURL(blogUrl);
};
xhr.open("GET", url);
xhr.send();
}
// make the function global so it can be accessible from anchor tag onclick
window.downloadFile = downloadFile;
Run the code now, and you will be able to download the file.
Note: If you get a CORS error while working in localhost, then do the following steps:
- Download gsutil from here.
- Extract the ZIP and paste the folder to a permanent location in your system.
- Open the terminal or command prompt in that extracted folder and run the following command in it:
./install.sh
- Once installed, run the following command to initialize it:
gcloud init
- It will ask for your project name too.
- After the project is set and gcloud is initialized, create a file named “cors.json” at the root of your project.
- Your “cors.json” must have the following content:
[
{
"origin": ["*"],
"method": ["GET"],
"maxAgeSeconds": 3600
}
]
- Then run the following command in your terminal:
gsutil cors set cors.json gs://<your-cloud-storage-bucket>
- Now try to download the file again, your CORS error should be fixed.
Delete File from Firebase Storage
First, replace the [delete button here] section with the following:
<form class="delete-form">
<input type="hidden" name="id" v-bind:value="file.id" />
<input type="hidden" name="name" v-bind:value="file.name" />
<input type="submit" value="Delete" />
</form>
Then add “deleteObject” in your import of “firebase-storage”. So your import line will look like this:
import { getStorage, ref as stRef, uploadBytes, getDownloadURL, deleteObject } from "https://www.gstatic.com/firebasejs/9.1.0/firebase-storage.js";
Then add the following event in your [updated event goes here] section:
updated: function () {
var forms = document.querySelectorAll(".delete-form");
for (var a = 0; a < forms.length; a++) {
forms[a].setAttribute("onsubmit", "onDeleteFormSubmit();");
}
}
This will attach an event listener to every delete form, which will be called when the form is submitted. Now you need to create the following function in your Javascript:
function onDeleteFormSubmit() {
event.preventDefault();
var form = event.target;
const tempDbRef = dbRef(database, "files/" + form.id.value);
set(tempDbRef, null);
const deleteStorageReference = stRef(storage, "files/" + form.name.value);
deleteObject(deleteStorageReference);
for (var a = 0; a < vueApp.files.length; a++) {
if (vueApp.files[a].id == form.id.value) {
vueApp.files.splice(a, 1);
break;
}
}
}
window.onDeleteFormSubmit = onDeleteFormSubmit;
This will first delete the data from the real-time database. Then it will delete the file from Firebase Storage. Finally, it will remove it from the Vue JS array, so it will automatically be removed from the HTML table too.
Now you will be able to upload files to the Firebase Storage and save its path in Realtime Database. And also to download and delete the files from it. If you face any problems facing this tutorial, kindly let us know in the comments section below.