File Uploads using Fetch API and VueJS
Part 3 of 4 in Using Fetch API with VueJSWe’ve talked about file uploads with Axios a ton of different ways. Since we are just comparing the Fetch API with Axios, I won’t do as many examples. However, we will touch on the differences between the Fetch API and Axios when uploading files. Once again, if you want to see exactly how this component works, check out our GitHub repo.
Step 1: Preparing Your File Upload with Fetch API
For this request, we will be using a POST
request. However, you can use any proper HTTP Verb such as POST
, PUT
, or PATCH
. The two main differences between this type of request that includes a file and one that doesn’t is the Content-Type
is not JSON and the body is Form Data. This is exactly the same as Axios. Let’s dive into that.
Step 2: Uploading a File with Fetch API and VueJS
The first thing we need to do is create our file input in our VueJS template. It should look like this:
<input type="file" @change="handleFileUpload( $event )"/>
This will be the same whether you are using Axios or the Fetch API. The big thing to note is we apply a change listener through @change
and pass the $event
to the listener. Let’s add that method to our component:
handleFileUpload( e ){
this.form.icon = e.target.files[0];
}
What this does, is once a user selects a file, we grab the file from the event and store it locally. We store it to our form.icon
reference so we can use it later on. What’s stored is a representation of the File
object {LINK_TO MDN}. We can use this to send the file through the Fetch API or Axios.
Now it’s time to implement both of our requests:
Fetch API File Upload
let formData = new FormData();
formData.append( 'method', this.form.method );
formData.append( 'icon', this.form.icon );
fetch( '<https://api.roastandbrew.coffee/api/v1/brew-methods>', {
method: 'POST',
headers: {
'Authorization': 'Bearer '+this.token,
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body: formData
} )
.then( function( response ){
if( response.status != 201 ){
this.fetchError = response.status;
}else{
response.json().then( function( data ){
this.fetchResponse = data;
}.bind(this));
}
}.bind(this));
Axios File Upload
let formData = new FormData();
formData.append( 'method', this.form.method );
formData.append( 'icon', this.form.icon );
axios.post(' <https://api.roastandbrew.coffee/api/v1/brew-methods>',
formData, {
headers: {
'Authorization': 'Bearer '+this.token,
'Content-Type': 'multipart/form-data'
}
} )
.then( function( response ){
this.axiosResponse = response.data;
}.bind(this))
.catch( function( error ){
this.axiosError = error;
}.bind(this));
Both of these request should look very similar to sending a standard POST request. However, there are a few key differences.
Let’s look at the differences between Fetch API request and the Axios. The first thing we do is implement a FormData()
object.. This allows us to handle and send files. We need this request to be a FormData
object so we can send files to the server.
let formData = new FormData();
formData.append( 'method', this.form.method );
formData.append( 'icon', this.form.icon );
The next difference is we need to change the Content-Type
to 'Content-Type': 'multipart/form-data'
. This alerts the endpoint we are using a multipart/form-data
request and the server should look for attached files. We have to add this header to Axios as well.
The final difference is in the body
setting. Instead of JSON.stringify()
we pass the FormData()
object we created (formData
) as the setting for body
. This is very similar to the Axios request where we pass formData
as the second parameter to the axios.post()
method.
Gotchas
There are a few gotchas with doing file uploads. First, as I mentioned in the intro, you can use PUT
to send files to the server as well. However, if you are using a Laravel backend, you have to send this as a POST
request and append _method=PUT
to the body (formData.append('_method', 'PUT')
). Laravel will not pick up a multipart/form-encoded
request through PUT
.
Next, if you’ve checked out the Uploading Files with VueJS and Axios Course, you’d notice a progress indicator. With Axios, you can easily build in a progress indicator to show progress on uploading large files. As of this writing, you can not do this with the Fetch API. I really hope they fix this soon since it’s huge for UX. If I run across a fix, I’ll update this article.
Conclusion
Uploading a file with the Fetch API and VueJS should look very similar to sending a POST
, PUT
, or PATCH
request with only a few changes. Next up, we will try to abstract some of the settings to a standard location to clean up the Fetch API requests and make them easier to use. If you have any questions, be sure to reach out on Twitter (@danpastori) or on the community!