In this tutorial, I will show you way to build React.js File Upload example with Rest API. The React App uses Axios and Multipart File for making HTTP requests, Bootstrap for progress bar. You also have a display list of files’ information (with download url).
More Practice:
– Typescript: React Typescript File Upload example
– React Image Upload with Preview example
– React Multiple Files upload example with Progress Bar
– React.js CRUD example to consume Web API
– React JWT Authentication (without Redux) example
– React + Redux: JWT Authentication example
Material UI instead:
Material UI File Upload example with Axios & Progress Bar
Drag-Drop instead: React Drag and Drop File Upload example
Contents
- Overview
- Technology
- Rest API for File Upload & Storage
- React App for upload/download Files
- Setup React File Upload Project
- Import Bootstrap to React File Upload App
- Initialize Axios for React HTTP Client
- Create Service for File Upload
- Create Component for Upload Files
- Add File Upload Component to App Component
- Configure Port for React File Upload App
- Run the App
- Further Reading
- Conclusion
- Source Code
Overview
We’re gonna create a React File upload application in that user can:
- see the upload process (percentage) with progress bar
- view all uploaded files
- link to download the file when clicking on the file name
Technology
- React 16
- Axios 0.19.2
- Bootstrap 4
Rest API for File Upload & Storage
Here is the API that our React App 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 APIs 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
React App for upload/download Files
After building the React project is done, the folder structure will look like this:
Let me explain it briefly.
– upload-files.service provides methods to save File and get Files using Axios.
– upload-files.component contains upload form, progress bar, display of list files with download url.
– App.js is the container that we embed all React components.
– http-common.js initializes Axios with HTTP base Url and headers.
– We configure port for our App in .env
Setup React File Upload Project
Open cmd at the folder you want to save Project folder, run command:
npx create-react-app react-file-upload
After the process is done. We create additional folders and files like the following tree:
public
src
components
upload-files.component.js
services
upload-files.service.js
App.css
App.js
index.js
package.json
Import Bootstrap to React File Upload App
Run command: npm install bootstrap
.
Open src/App.js and modify the code inside it as following-
import React, { Component } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
class App extends Component {
render() {
// ...
}
}
export default App;
Initialize Axios for React HTTP Client
Let’s install axios with command: npm install axios
.
Under src folder, we create http-common.js file with following code:
import axios from "axios";
export default axios.create({
baseURL: "http://localhost:8080",
headers: {
"Content-type": "application/json"
}
});
You can change the baseURL
that depends on REST APIs url that your Server configures.
Create Service for File Upload
This service will use Axios to send HTTP requests.
There are 2 functions:
upload(file)
: POST form data with a callback for tracking upload progressgetFiles()
: GET list of Files’ information
services/upload-files.service.js
import http from "../http-common";
class UploadFilesService {
upload(file, onUploadProgress) {
let formData = new FormData();
formData.append("file", file);
return http.post("/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
onUploadProgress,
});
}
getFiles() {
return http.get("/files");
}
}
export default new UploadFilesService();
– First we import Axios as http
from http-common.js.
– Inside upload()
method, we use FormData
to store key-value pairs. It helps to build an object which corresponds to HTML form using append()
method.
– 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.
– We call Axios post()
to send an HTTP POST for uploading a File to Rest APIs Server and get()
method for HTTP GET request to retrieve all stored files.
Create Component for Upload Files
Let’s create a File Upload UI with Progress Bar, Card, Button and Message.
First we create a React component template and import UploadFilesService
:
components/upload-files.component.js
import React, { Component } from "react";
import UploadService from "../services/upload-files.service";
export default class UploadFiles extends Component {
constructor(props) {
}
render() {
}
}
Then we define the state inside constructor()
method:
export default class UploadFiles extends Component {
constructor(props) {
super(props);
...
this.state = {
selectedFiles: undefined,
currentFile: undefined,
progress: 0,
message: "",
fileInfos: [],
};
}
}
Next we define selectFile()
method which helps us to get the selected Files from <input type="file" >
element later.
export default class UploadFiles extends Component {
...
selectFile(event) {
this.setState({
selectedFiles: event.target.files,
});
}
We use selectedFiles
for accessing current File as the first Item. Then we call UploadService.upload()
method on the currentFile
with a callback. So create following upload()
method:
export default class UploadFiles extends Component {
...
upload() {
let currentFile = this.state.selectedFiles[0];
this.setState({
progress: 0,
currentFile: currentFile,
});
UploadService.upload(currentFile, (event) => {
this.setState({
progress: Math.round((100 * event.loaded) / event.total),
});
})
.then((response) => {
this.setState({
message: response.data.message,
});
return UploadService.getFiles();
})
.then((files) => {
this.setState({
fileInfos: files.data,
});
})
.catch(() => {
this.setState({
progress: 0,
message: "Could not upload the file!",
currentFile: undefined,
});
});
this.setState({
selectedFiles: undefined,
});
}
The progress will be calculated basing on event.loaded
and event.total
.
If the transmission is done, we call UploadService.getFiles()
to get the files’ information and assign the result to fileInfos
state, which is an array of {name, url}
objects.
We also need to do this work in componentDidMount()
method:
export default class UploadFiles extends Component {
...
componentDidMount() {
UploadService.getFiles().then((response) => {
this.setState({
fileInfos: response.data,
});
});
}
Now we implement the render function of the Upload File UI. Add the following code inside render()
:
export default class UploadFiles extends Component {
...
render() {
const {
selectedFiles,
currentFile,
progress,
message,
fileInfos,
} = this.state;
return (
<div>
{currentFile && (
<div className="progress">
<div
className="progress-bar progress-bar-info progress-bar-striped"
role="progressbar"
aria-valuenow={progress}
aria-valuemin="0"
aria-valuemax="100"
style={{ width: progress + "%" }}
>
{progress}%
</div>
</div>
)}
<label className="btn btn-default">
<input type="file" onChange={this.selectFile} />
</label>
<button className="btn btn-success"
disabled={!selectedFiles}
onClick={this.upload}
>
Upload
</button>
<div className="alert alert-light" role="alert">
{message}
</div>
<div className="card">
<div className="card-header">List of Files</div>
<ul className="list-group list-group-flush">
{fileInfos &&
fileInfos.map((file, index) => (
<li className="list-group-item" key={index}>
<a href={file.url}>{file.name}</a>
</li>
))}
</ul>
</div>
</div>
);
}
}
In the code above, we use Bootstrap Progress Bar:
.progress
as a wrapper- inner
.progress-bar
to indicate the progress .progress-bar
requiresstyle
to set the width by percentage.progress-bar
also requiresrole
and some aria attributes to make it accessible- label of the progress bar is the text within it
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.
You can simplify import statement with:
Absolute Import in React
Add File Upload Component to App Component
Open App.js, import and embed the UploadFiles
Component tag.
import React from "react";
import "./App.css";
import "bootstrap/dist/css/bootstrap.min.css";
import UploadFiles from "./components/upload-files.component";
function App() {
return (
<div className="container" style={{ width: "600px" }}>
<div style={{ margin: "20px" }}>
<h3>bezkoder.com</h3>
<h4>React upload Files</h4>
</div>
<UploadFiles />
</div>
);
}
export default App;
Configure Port for React File Upload App
Because most of HTTP Server use CORS configuration that accepts resource sharing restricted to some sites or ports, and if you use the Project in this post for making Server, you need to configure port for our App.
In project folder, create .env file with following content:
PORT=8081
So our app will run at port 8081.
Run the App
You can find how to implement the Rest APIs 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
Run this React File Upload Axios: npm start
.
Open Browser with url http://localhost:8081/
and check the result.
Further Reading
- https://github.com/axios/axios
- Axios File Upload example
- React Component
- Bootstrap 4 Progress
- React.js CRUD example to consume Web API
- React JWT Authentication (without Redux) example
– React Image Upload with Preview example
Conclusion
Today we’re learned how to build an example for File upload using React and Axios. We also provide the ability to show list of files, upload progress bar using Bootstrap, and to download file from the server.
Happy Learning! See you again.
Similar React App using Hooks: React Hooks File Upload example with Axios & Progress Bar
If you want to upload multiple files at once like this:
You can find the instruction here:
React Multiple Files upload example with Progress Bar
Or using Material UI instead:
Material UI File Upload example with Axios & Progress Bar
Source Code
The source code for the React Client is uploaded to Github.
– Typescript: React Typescript File Upload example
– Drag-Drop instead: React Drag and Drop File Upload example
Thanks for this nice tuto!
Thanks!
https://www.bezkoder.com/react-file-upload-axios/
Set to 5MB
Tomcat started on port(s): 8080 (http) with context path ”
[2m2021-10-08 10:44:28.729[0;39m [32m INFO[0;39m [35m20376[0;39m [2m—[0;39m [2m[ main][0;39m [36mb.s.f.u.SpringBootUploadFilesApplication[0;39m [2m:[0;39m Started SpringBootUploadFilesApplication in 1.81 seconds (JVM running for 2.623)
back end works
http://localhost:8080/upload
from postman: message”: “Uploaded the file successfully: InProgressReport.txt”
Front End: export default axios.create({
baseURL: “http://localhost:8080”,
headers: {
“Content-type”: “application/json”
}
});
Selecting a tiny text file…but still get ‘Could not upload the file!’
Front end running by http://localhost:8081/
I was debugging for file values:
In uploads-files-service, formData.append(“file”, file);
file= name:’InProgressReport2.txt’
lastModifiedDate:Thu Aug 19 2021 13:52:05 GMT-0400 (Eastern Daylight Time)
lastModified:1629395525773
size:1520
type:’text/plain’
webkitRelativePath:”
looks right to me.
Next step to debug? How can I tell if the front end is talking\reaching to the back end?
Thank you in advance. I am new to this reactjs stuff.
Rob
bezkoder,
Thank you for providing the tutorial.
I have the backend running on my PC (com.bezkoder.spring.files.upload) and it works with POSTMAN http://localhost:8080/upload
“message”: “Uploaded the file successfully: InProgressReport.txt”
I am now testing the React File Upload from C:\SpringExamples\spring-boot-upload-multipart-files-master
running on http://localhost:8081.
The UI displays, I can select a file but always get the ‘Could not upload the file’ response.
Where do I start to debug or re-configure so this works?
Thank you in advance for your support,
Rob
Hi, you can check your Spring Boot backend with limit file size configuration (in
application.properties
).Thanks. This tutorial is really really helpful and useful to study.
HI,
Do you have an example with DJango-storages as well? I have the same implementation set up in the frontend, but currently running into issues when uploading a 1GB file.
Thank you!
Hello Sir!
I really appreciate your tutorial,
but could you make a tutorial to connect React upload/download file with Node.js API?
I’ve followed your ‘upload image to database with Node.js tutorial’ but I want to try it with React instead of jQuery, and I don’t know how to…
Thank you! 🙂
Hi, you can find the Node.js server that provides APIs for this React Client at:
Node.js Express File Upload Rest API example using Multer