In this tutorial, I will show you way to build React.js Image Upload with Preview (functional component) to a 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 images’ information (with download url).
More Practice:
– Typescript: Upload Image in React Typescript example (with Preview)
– React Multiple Images Upload with Preview example
– Drag and Drop File Upload with React Hooks example
– React Hooks CRUD example with Axios and Web API
– React Form Validation with Hooks example
– React Hooks: JWT Authentication (without Redux) example
– React + Redux: JWT Authentication example
– React Custom Hook
Serverless:
– React Hooks + Firebase Realtime Database: CRUD App
– React Hooks + Firestore example: CRUD app
Using React Components instead:
React.js Image Upload with Preview Display example
Contents
- Overview
- Technology
- Rest API for File Upload & Storage
- React App for Image upload with preview
- Setup React.js Image Upload with Preview Project
- Import Bootstrap to React.js Image Upload App
- Initialize Axios for React HTTP Client
- Create Service for File Upload
- Create Functional Component for Upload Images
- Add Image Upload Functional Component to App Component
- Configure Port for React Image Upload App
- Run the App
- Conclusion
- Further Reading
- Source Code
Overview
We’re gonna create a React.js Image upload with Preview example using Hooks in that user can:
- display the preview of image before uploading
- see the upload process (percentage) with progress bar
- view all uploaded images
- link to download the image when clicking on the file name
For multiple Images upload with preview, please visit:
React Multiple Images Upload with Preview example
Technology
- React 18/17/16
- Axios 0.27.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 Image upload with preview
After building the React.js project is done, the folder structure will look like this:
Let me explain it briefly.
– ImageUploadService provides methods to save File and get Files using Axios.
– ImageUpload is a React.js functional component contains upload form, image preview, progress bar, display of list of images 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.js Image Upload with Preview Project
Open cmd at the folder you want to save Project folder, run command:
npx create-react-app react-js-image-upload-preview
Or: yarn create react-app react-js-image-upload-preview
After the process is done. We create additional folders and files like the following tree:
public
src
components
ImageUpload.js
services
FileUploadService.js
App.css
App.js
index.js
package.json
Import Bootstrap to React.js Image Upload App
Run command: npm install [email protected]
Or: yarn add [email protected]
Open src/App.js and modify the code inside it as following-
import React from "react";
import "./App.css";
import "bootstrap/dist/css/bootstrap.min.css";
function App() {
return (
...
);
}
export default App;
Initialize Axios for React HTTP Client
Let’s install axios with command: npm install [email protected]
.
Or: yarn add [email protected]
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/FileUploadService.js
import http from "../http-common";
const upload = (file, onUploadProgress) => {
let formData = new FormData();
formData.append("file", file);
return http.post("/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
onUploadProgress,
});
};
const getFiles = () => {
return http.get("/files");
};
export default {
upload,
getFiles,
};
– 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 Functional Component for Upload Images
Let’s create a Image Upload UI with Progress Bar, Card, Button and Message.
First we create a React template with React Hooks (useState
, useEffect
) and import FileUploadService
:
components/FileUpload.js
import React, { useState, useEffect } from "react";
import UploadService from "../services/FileUploadService";
const ImageUpload = () => {
return (
);
};
export default ImageUpload;
Then we define the state using React Hooks:
const ImageUpload = () => {
const [currentFile, setCurrentFile] = useState(undefined);
const [previewImage, setPreviewImage] = useState(undefined);
const [progress, setProgress] = useState(0);
const [message, setMessage] = useState("");
const [imageInfos, setImageInfos] = useState([]);
...
}
Next we define selectFile()
method which helps us to get the selected Files from <input type="file" >
element later.
const ImageUpload = () => {
...
const selectFile = (event) => {
setCurrentFile(event.target.files[0]);
setPreviewImage(URL.createObjectURL(event.target.files[0]));
setProgress(0);
setMessage("");
};
...
}
We use event.target.files[0]
for accessing current File as the first Item.
We use URL.createObjectURL()
static method to get the image preview URL as previewImage
. This method produces a DOMString
including a URL describing the object provided in the parameter. The URL life is tied to the document in the window on which it was created.
We call UploadService.upload()
method on the currentFile
with a callback. So create following upload()
method:
const ImageUpload = () => {
...
const upload = () => {
setProgress(0);
UploadService.upload(currentFile, (event) => {
setProgress(Math.round((100 * event.loaded) / event.total));
})
.then((response) => {
setMessage(response.data.message);
return UploadService.getFiles();
})
.then((files) => {
setImageInfos(files.data);
})
.catch((err) => {
setProgress(0);
if (err.response && err.response.data && err.response.data.message) {
setMessage(err.response.data.message);
} else {
setMessage("Could not upload the Image!");
}
setCurrentFile(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 images’ information and assign the result to imageInfos
state, which is an array of {name, url}
objects.
We also need to do this work in the Effect Hook useEffect()
method which serves the same purpose as componentDidMount()
:
const ImageUpload = () => {
...
useEffect(() => {
UploadService.getFiles().then((response) => {
setImageInfos(response.data);
});
}, []);
}
Now we return the Upload File UI. Add the following code inside return()
block:
const ImageUpload = () => {
...
return (
<div>
<div className="row">
<div className="col-8">
<label className="btn btn-default p-0">
<input type="file" accept="image/*" onChange={selectFile} />
</label>
</div>
<div className="col-4">
<button
className="btn btn-success btn-sm"
disabled={!currentFile}
onClick={upload}
>
Upload
</button>
</div>
</div>
{currentFile && (
<div className="progress my-3">
<div
className="progress-bar progress-bar-info"
role="progressbar"
aria-valuenow={progress}
aria-valuemin="0"
aria-valuemax="100"
style={{ width: progress + "%" }}
>
{progress}%
</div>
</div>
)}
{previewImage && (
<div>
<img className="preview" src={previewImage} alt="" />
</div>
)}
{message && (
<div className="alert alert-secondary mt-3" role="alert">
{message}
</div>
)}
<div className="card mt-3">
<div className="card-header">List of Images</div>
<ul className="list-group list-group-flush">
{imageInfos &&
imageInfos.map((img, index) => (
<li className="list-group-item" key={index}>
<p>
<a href={img.url}>{img.name}</a>
</p>
<img src={img.url} alt={img.name} height="80px" />
</li>
))}
</ul>
</div>
</div>
);
};
export default ImageUpload;
We allow only image format, so the input
element will have accept="image/*"
attribute.
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
The preview of uploading image is shown: <img className="preview" src={previewImage} alt="" />
To display List of uploaded images, we iterate over imageInfos
array using map()
function. On each image item, we use img.url
as href
attribute and img.name
for showing text.
Add Image Upload Functional Component to App Component
Open App.js, import and embed the ImageUpload
Component tag.
import React from "react";
import "./App.css";
import "bootstrap/dist/css/bootstrap.min.css";
import ImageUpload from "./components/ImageUpload";
function App() {
return (
<div className="container">
<h3>bezkoder.com</h3>
<h4>React.js Image Upload with Preview</h4>
<div className="content">
<ImageUpload />
</div>
</div>
);
}
export default App;
App.css
.container{
width: 600px !important;
margin: 20px;
}
.content {
margin: 20px 0;
}
.preview {
max-width: 200px;
}
Configure Port for React Image 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 following Project for making Server:
– 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
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
.
Or: yarn start
.
Open Browser with url http://localhost:8081/
and check the result.
Conclusion
Today we’re learned how to build a React functional component application (React Hooks) for upload Images with Preview using Axios, Bootstrap with Progress Bar. We also provide the ability to show list of images, upload progress percentage, and to download Image from the server.
For Multiple Images Upload like this:
Please visit:
React.js Multiple Images Upload with Preview example
Using React Components instead:
React.js Image Upload with Preview Display example
Happy Learning! See you again.
Further Reading
- https://github.com/axios/axios
- React Hooks
- React Custom Hook
- Bootstrap 4 Progress
- React Hooks CRUD example with Axios and Web API
- React Hooks: JWT Authentication (without Redux) example
- React + Redux: JWT Authentication with Hooks
Fullstack:
– React + Spring Boot + MySQL: CRUD example
– React + Spring Boot + PostgreSQL: CRUD example
– React + Spring Boot + MongoDB: CRUD example
– React + Node.js + Express + MySQL: CRUD example
– React + Node.js + Express + PostgreSQL example
React Redux + Node.js + Express + MySQL: CRUD example
– React + Node.js + Express + MongoDB example
– React + Django + Rest Framework example
Serverless:
– React Hooks + Firebase Realtime Database: CRUD App
– React Hooks + Firestore example: CRUD app
Source Code
You can find the complete source code for this tutorial at Github.
Typescript version: Upload Image in React Typescript example (with Preview)
More Practice: Drag and Drop File Upload with React Hooks example