In this tutorial, I will show you an Axios File Upload example (with/without progress) using multipart/form-data.
Related Posts:
– Axios Tutorial: Get/Post/Put/Delete request example
– Axios Interceptors tutorial with example
– React File Upload with Axios and Progress Bar
– Vue File Upload example with Axios and Progress Bar
Contents
- Axios Features
- How to install Axios
- Axios Response Object schema
- Axios File Upload with multipart/form-data
- Axios File Upload Response Body
- Axios File Upload Error handling
- Axios File Upload Error handling with async-await
- Axios File Upload Progress
- Get all uploaded files
- Rest API for File Upload
- Axios File Upload example
- Conclusion
- Further Reading
Axios Features
Axios can run in the Node.js and Browser with the same codebase.
– On the server-side it uses the native Node.js http
module
– On the client-side (browser) it uses XMLHttpRequests
Additionally, there are important features that you should know:
- Supports the Promise API
- Intercept request and response (Axios Interceptors tutorial)
- Transform request and response data
- Cancel requests
- Automatic transforms for JSON data
- Client side support for protecting against XSRF
(from https://github.com/axios/axios#features)
How to install Axios
We can add Axios to our project/code with one of following simple ways:
– npm:
npm install axios
– bower:
bower install axios
– yarn:
yarn add axios
– CDN:
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
Or:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
Axios Response Object schema
The response for a Axios request contains:
data
: parsed response body provided by the serverstatus
: HTTP status codestatusText
: HTTP status messageheaders
: HTTP headers (lower case)config
: the request config that was provided toaxios
request
: the last client request instance that generated this response
For example:
{
"data": {
"message": "Uploaded the file successfully: bezkoder.sql"
},
"status": 200,
"statusText": "OK",
"headers": {
"content-length": "58",
"content-type": "application/json; charset=utf-8"
},
"config": {
"transitional": {
"silentJSONParsing": true,
"forcedJSONParsing": true,
"clarifyTimeoutError": false
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1,
"headers": {
"Accept": "application/json, text/plain, */*"
},
"baseURL": "http://localhost:8080",
"method": "post",
"url": "/upload"
}
}
Axios File Upload with multipart/form-data
We will use FormData
object for constructing a set of key/value pairs: form fields and their values, this object is easily sent using the axios.post()
method.
Remember to set the encoding type to "multipart/form-data"
.
let formData = new FormData();
formData.append("file", selectedFile);
axios.post('/bezkoder.com/upload', formData, {
headers: {
"Content-Type": "multipart/form-data",
}
});
Axios File Upload Response Body
Axios Response Object has data
field that contains the parsed response body.
We can use then
or await to receive the response body as follows:
axios.post('/bezkoder.com/upload', formData, {
headers: {
"Content-Type": "multipart/form-data",
}
})
.then(function (response) {
console.log(response.data);
});
const { data } = await axios.post(url);
Axios File Upload Error handling
We use catch()
for handling errors.
axios.post('/bezkoder.com/upload', formData, {
headers: {
"Content-Type": "multipart/form-data",
}
})
.then(...)
.catch(function (error) {
if (error.response) { // get response with a status code not in range 2xx
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) { // no response
console.log(error.request);
// instance of XMLHttpRequest in the browser
// instance ofhttp.ClientRequest in node.js
} else { // Something wrong in setting up the request
console.log('Error', error.message);
}
console.log(error.config);
});
Axios File Upload Error handling with async-await
If you want to use async-await, just wrap the axios call with try/catch block.
async function uploadFile() {
try {
const response = await axios.post('/bezkoder.com/upload', formData, {
headers: {
"Content-Type": "multipart/form-data",
}
});
console.log(response);
} catch (error) {
if (error.response) { // get response with a status code not in range 2xx
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) { // no response
console.log(error.request);
} else { // Something wrong in setting up the request
console.log('Error', error.message);
}
console.log(error.config);
}
}
Axios File Upload Progress
We pass onUploadProgress
to exposes progress events. This progress event are expensive (change detection for each event), so you should only use when you want to monitor it.
The progress will be calculated basing on event.loaded
and event.total
.
async function uploadFile() {
const onUploadProgress = (event) => {
const percentage = Math.round((100 * event.loaded) / event.total);
console.log(percentage);
};
try {
const response = await axios.post('/bezkoder.com/upload', formData, {
headers: {
"Content-Type": "multipart/form-data",
}
onUploadProgress,
});
console.log(response);
} catch (error) {
...
}
}
You can use Bootstrap Progress Bar for displaying the percentage
:
.progress
as a wrapper- inner
.progress-bar
to indicate the progress .progress-bar
requiresstyle
to set thewidth
by percentage.progress-bar
also requiresrole
and some aria attributes to make it accessible- label of the progress bar is the text within it (
innerHTML
) aria-valuenow
attribute for percentage (0-100)
<div id="progress" class="progress">
<div
id="progress-bar"
class="progress-bar progress-bar-info"
role="progressbar"
aria-valuemin="0"
aria-valuemax="100"
></div>
</div>
let progressBarElement = document.getElementById("progress-bar");
progressBarElement.innerHTML = "0%";
progressBarElement.setAttribute("aria-valuenow", 0);
progressBarElement.style.width = "0%";
const onUploadProgress = (event) => {
const percentage = Math.round((100 * event.loaded) / event.total);
progressBarElement.innerHTML = percentage + "%";
progressBarElement.setAttribute("aria-valuenow", percentage);
progressBarElement.style.width = percentage + "%";
};
Get all uploaded files
We use Axios to send HTTP GET request to get the files’ information and assign the result to fileInfos
array, which is an array of {name, url}
objects.
To display List of uploaded files, we iterate over fileInfos
array using map()
function. On each file item, we use file.url
as href
attribute and file.name
for showing text.
function getHTMLFiles(fileInfos) {
if (fileInfos && fileInfos.length) {
const files = fileInfos.map(
(file, index) =>
`<li key='` + index + `'>\
<a href='` + file.url + `'>` + file.name + `</a>\
</li>`
);
return (
`<div>List of Files</div>\
<ul>` +
files.join("") +
`</ul>`
);
}
return `No file was found!`;
}
async function getFiles() {
try {
const res = await axios.get("/bezkoder.com/files");
filesElement.innerHTML = getHTMLFiles(res.data);
} catch (err) {
...
}
}
Rest API for File Upload
Here is the API that our Axios Client will work with:
Methods | Urls | Actions |
---|---|---|
POST | /upload | upload a File |
GET | /files | get List of Files (name & url) |
GET | /files/[filename] | download a File |
You can find how to implement the Rest API Server at one of following posts:
– Node.js Express File Upload Rest API example
– Node.js Express File Upload to MongoDB example
– Node.js Express File Upload to Google Cloud Storage example
– Spring Boot Multipart File upload (to static folder) example
Or: Spring Boot Multipart File upload (to database) example
Note: You need to configure CORS with origin: "*"
for working well with the example in this tutorial.
Axios File Upload example
We’re gonna create a Axios File Upload example in that user can:
- see the upload process (percentage) with progress bar
- view all uploaded files
- download the file by clicking on the file name
Click on Get List of Files button:
– First we import Axios and Bootstrap, then we write some HTML code for the UI.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Axios File upload</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
/>
</head>
<body>
<div class="container" style="max-width: 600px">
<h3 class="mb-3">Axios File Upload</h3>
<div class="input-group">
<div class="custom-file">
<input id="input-file" type="file" class="custom-file-input" />
<label id="input-file-label" class="custom-file-label" for="input-file">Choose file</label>
</div>
<div class="input-group-append">
<button
class="btn btn-outline-success"
type="button"
onClick="uploadFile()"
>
Upload
</button>
</div>
</div>
<div id="progress" class="progress my-3" style="display: none">
<div
id="progress-bar"
class="progress-bar progress-bar-info"
role="progressbar"
aria-valuemin="0"
aria-valuemax="100"
></div>
</div>
<div id="message" class="alert-light" role="alert"></div>
<button class="btn btn-info btn-sm my-3" onClick="getFiles()">
Get List of Files
</button>
<div id="list-files" class="card" style="display: none"></div>
<p class="mt-3">
©
<a href="https://www.bezkoder.com" target="_blank">bezkoder.com</a>
</p>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="main.js"></script>
</body>
</html>
This is the user interface:
For 2 onClick
events, there are 2 functions that use Axios for working with Rest API Server:
uploadFile()
: POST form data with a callback for tracking upload progressgetFiles()
: GET list of Files’ information
main.js
const instance = axios.create({
baseURL: "http://localhost:8080"
});
document.getElementById("input-file").addEventListener("change", (e) => {
if (e.target.files.length) {
document.getElementById("input-file-label").innerHTML = e.target.files[0].name;
}
});
async function uploadFile() {
let messageElement = document.getElementById("message");
messageElement.innerHTML = "";
const selectedFile = document.getElementById("input-file").files[0];
let formData = new FormData();
formData.append("file", selectedFile);
document.getElementById("progress").style.display = "flex";
let progressBarElement = document.getElementById("progress-bar");
progressBarElement.innerHTML = "0%";
progressBarElement.setAttribute("aria-valuenow", 0);
progressBarElement.style.width = "0%";
const onUploadProgress = (event) => {
const percentage = Math.round((100 * event.loaded) / event.total);
progressBarElement.innerHTML = percentage + "%";
progressBarElement.setAttribute("aria-valuenow", percentage);
progressBarElement.style.width = percentage + "%";
};
try {
const res = await instance.post("/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
onUploadProgress,
});
const result = {
status: res.status + "-" + res.statusText,
headers: res.headers,
data: res.data
};
messageElement.innerHTML = htmlizeResponse(result);
} catch (err) {
messageElement.innerHTML = htmlizeResponse(err);
}
}
async function getFiles() {
let messageElement = document.getElementById("message");
messageElement.innerHTML = "";
let filesElement = document.getElementById("list-files");
filesElement.innerHTML = "";
try {
const res = await instance.get("/files");
const result = {
status: res.status + "-" + res.statusText,
headers: res.headers,
};
messageElement.innerHTML = htmlizeResponse(result);
filesElement.innerHTML = getHTMLFiles(res.data);
document.getElementById("list-files").style.display = "block";
} catch (err) {
messageElement.innerHTML = htmlizeResponse(err);
}
}
function htmlizeResponse(res) {
return (
`<div class="alert alert-secondary mt-2" role="alert"><pre>` +
JSON.stringify(res, null, 2) +
"</pre></div>"
);
}
function getHTMLFiles(fileInfos) {
if (fileInfos && fileInfos.length) {
const files = fileInfos.map(
(file, index) =>
`<li class="list-group-item" key='` + index + `'>\
<a href='` + file.url + `'>` + file.name + `</a>\
</li>`
);
return (
`<div class="card-header">List of Files</div>\
<ul class="list-group list-group-flush">` +
files.join("") +
`</ul>`
);
}
return `No file was found!`;
}
Conclusion
With this Axios tutorial, you’ve known many ways to upload file using Axios (with multipart/form-data). You can also use it in:
– React App: React File Upload with Axios
– Vue App: Vue File Upload example with Axios
Happy Learning! See you again.
Further Reading
- https://github.com/axios/axios
- Axios Tutorial: Get/Post/Put/Delete request example
- Axios Interceptors tutorial with example
- React CRUD example with Axios & React Router
- React Redux CRUD example with Axios & React Router
- Vue 2 CRUD Application with Axios & Vue Router
- Vue 3 CRUD example with Axios & Vue Router