Introduction and Goal
Welcome to this video. Great to have you here. In this video I want to show you how you can upload files from within your Vue application, so how you can allow the user to select a file and then ship it to some RESTful API endpoint you got somewhere. Let's dive right into it.
Project Setup and Target File
Of course, to demonstrate file upload we need a Vue application, so I created a new one with the Vue CLI. I used the webpack template and I didn't change anything. Now in this application we by default get this App.vue file where we simply got router installed, load this Hello World page, and this is the page I'll work in. So I'll simply clean everything in there so that I just have this div and you could change the styling and everything but I don't care. I want to quickly add my file input field, add a button that allows me to upload it and show you how to upload a file. Let's start simple though. Let's start by adding an input field of type file which is a default HTML element.
Nothing viewers about it. The Vue part is that I will now add an event listener: @change that will trigger whenever the user selects a new file, and then I want to execute, let's say, onFileSelected—this method. Now I will have to add this in my Vue instance in this component here, so I'll add the methods object onFileSelected and there I will actually get my event and let's for now simply log it to the console to see what's inside of it. If I now save everything and I go back to my app we can ignore that warning with the extra space that's missing and simply choose a file here. If I click this and add a file you see an event as output down there. And this file here is actually holding the normal event object with the target which is the file input. But we got one useful property: the files property which is an array of all the files that the user chose. You could add a multi-select tool here too. Here I only got one file so it's the first element in this array and that is the file we can upload. So the goal is to then store that file.
So in my data object here I'll replace message with selectedFile and initially that's null. In onFileSelected though I'll set this.selectedFile equal to event.target.files[0], the first element. There: this is the file the user selected. Now we stored it here but we want to upload it, right? Now for that I will add a button where I will say Upload and where I will add a click listener to execute onUpload or whatever name you want to give to this method. So I'll then add my onUpload method here which takes no arguments and here I now want to send an HTTP request to some API endpoint that accepts the file.
We could send the file in both a binary format or as I will do it as part of FormData which is a JavaScript object meant to mix normal fields and files and pack it all into one request body and send it to the backend. Now you might have your own backend. I will use a function of Firebase Cloud Function I built in this video—link is also in the video description. This Firebase Cloud Function accepts FormData and stores a file on the Firebase Cloud Storage. So that is what I will use and for that I will access my Firebase console of that project and first of all remove all files I have in the storage so that we can really see that it worked. And then I will go to Functions. Here are all the functions I created and I will use that endpoint of my HTTP function. Now you won't be able to use that because that project will have been deleted by the time you're viewing this, but you can of course build your own function by following that video I mentioned. So here I'll copy that endpoint and with that we need to send a request, right? And how do we do that? I will install a special package for this. I will use npm for that: npm install --save axios. Axios is a third-party package not related to Vue which simply makes it easy for us to send AJAX requests. That's the idea behind Axios. Thereafter I'll restart my development server and now I can simply import axios from 'axios' in this Vue component here.
Creating FormData and Posting the File
Now with that imported I want to use it here in the upload onUpload function. I can use the post method to send a POST request and here I first of all need to specify the URL which is the URL I just copied. The second part then is that I will need to set the data I want to send and as I said I want to send FormData because this is the format my backend here expects. So I'll create a new constant fd, initialize a new FormData object. A FormData is a default JavaScript object, we don't need to import or install that, and then I can call append to append a new piece of data to that FormData object. I'll give it a name of 'image'—name is up to you—and the value will be this.selectedFile, so the file the user picked which we then stored, and I'll also keep the file name. I'll take it from this.selectedFile, there will be a name property which is the original file name. With that we get the FormData prepared. We can now simply add it as a second argument here and then chain up .then() call because axios will return a promise and there we should eventually get a response which I'll simply log to the console.
Testing the Upload and Verifying Firebase Storage
If I save this and we reload our application, if I now choose my file here and I clear the console and then hit Upload it takes a while but then we should see a response here. It is status code 200, looks good. Data holds 'it worked'—that is the response my Firebase backend gives me if it worked. And if we visit the Storage on my Firebase backend I indeed see the file and another file because of another cloud function which automatically transformed that file. But this is now working. This is the file I picked and I uploaded.
Showing Upload Progress with Axios
Now that's great, but let's enhance this. Let's say we want to see the progress whilst this is uploading, especially useful for bigger files of course. Axios makes this easy. We can pass a third argument to the post method. This is an argument where we can configure this request by passing a JavaScript object, and there we can add the onUploadProgress event handler so to say. Here we simply store a function where we get the upload event, and now we can simply console.log 'upload progress' and the upload event has two important fields. The first one is the loaded field. This is holding a number in bytes how much we uploaded. We can divide this by the second important field uploadEvent.total—that is the total amount we want to upload. So by dividing loaded by total we get the percentage essentially. Now we can use Math.round on that but not on that like this, but instead let's multiply it by 100 to get a full integer and I will then simply append '%' at the end. Now this should also give me percentages whilst it's uploading the file. Let's try this out. Let's clear the console and pick a file and let's press Upload and you see we get the upload progress percentages and then after a while also the response. So that's pretty cool and this is how easy it is to upload a file.
Now when everything, sometimes what you sometimes want to do is you want to hide that input element and instead have some button where you maybe say 'Pick file' and that button should then trigger this input. You can do this by first of all setting the style and set display to none here to not show this input. And now we want to basically proxy a click on this button to this input. Here now this is done relatively easy. We can use a feature by Vue.js called refs. We can add the ref key here and assign this a name by which we then can access this element like fileInput, and then on the button we can add a click listener and set this equal to $refs which is an object in which Vue manages all the refs you set up with the ref key and then fileInput and now I can simply execute click here to proxy my click on that button to that input as if the user had directly clicked on it.
Wrap-up and Goodbye
Now if I save this I clear the console and I click on 'Pick file' I open that file picker through that button and I can still upload that file just as before. And this is actually it; this is how easy we can implement all kinds of things related to file upload in a Vue app. So I hope this was helpful. It helps you with your next project. Would be awesome to welcome you to future videos. Have a great time. Bye.