Building an Image Upload Application with React JS and Node JS

Introduction

In this tutorial, we will build a full-stack web application using React JS for the frontend and Node JS with Express for the backend. The application allows users to upload images one at a time and view all uploaded images. We will use Multer for handling file uploads in Node JS and React Router for page navigation in the React JS application.

Basic requirements
  • Basic knowledge of JavaScript, React JS, and Node JS.
  • Node.js installed on your system.
  • Multer for file uploads.
Setting Up the Node JS Backend

We will start by setting up the backend server using Node JS and Express.

1. Initialize Node Project :

Create a new folder for your backend and run the following commands.

				
					mkdir image-upload-backend
cd image-upload-backend
npm init -y

				
			
2. Install Required Dependencies :

Install the necessary dependencies, including Express and Multer for file handling.

				
					npm install express multer cors

				
			
3. Create the Server (index.js) :

Create a new file named 'index.js' and set up the Express server.

				
					const express = require('express');
const multer = require('multer');
const cors = require('cors');
const path = require('path');
const fs = require('fs');

const app = express();
app.use(cors());
app.use(express.static('uploads'));  // Serve static files from uploads folder

// Set storage engine for Multer
const storage = multer.diskStorage({
  destination: './uploads',
  filename: (req, file, cb) => {
    cb(null, Date.now() + path.extname(file.originalname)); // Append current timestamp to file name
  }
});

// Initialize upload variable
const upload = multer({
  storage: storage,
  limits: { fileSize: 1000000 },  // 1MB file size limit
});

// API for uploading images
app.post('/upload', upload.single('image'), (req, res) => {
  if (!req.file) {
    return res.status(400).send('No file uploaded.');
  }
  res.send(`Image uploaded: ${req.file.filename}`);
});

// API to get all uploaded images
app.get('/images', (req, res) => {
  fs.readdir('./uploads', (err, files) => {
    if (err) return res.status(500).send('Unable to fetch images');
    res.json(files);
  });
});

app.listen(5000, () => {
  console.log('Server started on http://localhost:5000');
});

				
			

This code sets up two endpoints :

  1. '/upload' : Allows users to upload a single image.
  2. '/images' : Returns the list of all uploaded images.
4. Create an Uploads Folder :

Make sure you create an uploads folder in the root of your backend project to store the images.

				
					mkdir uploads

				
			
Setting Up the React JS Frontend
1. Create a New React Application :

Create a new folder for the frontend and run the following commands to create a React app using Vite:

				
					mkdir image-upload-frontend
cd image-upload-frontend
npm create vite@latest

				
			

Choose React when prompted and set up the project. Install additional required packages :

				
					npm install axios react-router-dom

				
			
2. Create Pages and Components :

We will create two main pages :

  • A page to upload images.
  • A page to view all uploaded images.
3. Create File Upload Page (UploadPage.jsx) :

This page will allow users to upload images.

				
					import { useState } from 'react';
import axios from 'axios';

const UploadPage = () => {
  const [file, setFile] = useState(null);
  const [message, setMessage] = useState('');

  const handleFileChange = (e) => {
    setFile(e.target.files[0]);
  };

  const handleUpload = async () => {
    const formData = new FormData();
    formData.append('image', file);

    try {
      const res = await axios.post('http://localhost:5000/upload', formData, {
        headers: { 'Content-Type': 'multipart/form-data' },
      });
      setMessage(res.data);
    } catch (err) {
      setMessage('Error uploading file');
    }
  };

  return (
    <div>
      <h1>Upload Image</h1>
      
      <button>Upload</button>
      <p>{message}</p>
    </div>
  );
};

export default UploadPage;

				
			
4. Create Image Gallery Page (GalleryPage.jsx) :

This page will display all uploaded images.

				
					import { useState, useEffect } from 'react';
import axios from 'axios';

const GalleryPage = () =&gt; {
  const [images, setImages] = useState([]);

  useEffect(() =&gt; {
    const fetchImages = async () =&gt; {
      const res = await axios.get('http://localhost:5000/images');
      setImages(res.data);
    };

    fetchImages();
  }, []);

  return (
    <div>
      <h1>Image Gallery</h1>
      <div>
        {images.map((image, index) =&gt; (
          <img decoding="async" src="5000/${image}`}" alt="{image}" width="200" />
        ))}
      </div>
    </div>
  );
};

export default GalleryPage;

				
			
5. Set Up React Router (App.jsx) :

We will use React Router to navigate between the upload page and the gallery page.

				
					import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import UploadPage from './UploadPage';
import GalleryPage from './GalleryPage';

function App() {
  return (
    
      <nav>
        Upload Image
        View Gallery
      </nav>
      
        &lt;Route path=&quot;/&quot; element={} /&gt;
        &lt;Route path=&quot;/gallery&quot; element={} /&gt;
      
    
  );
}

export default App;

				
			
6. Start the React Application :

Navigate to your React project directory and run.

				
					npm install
npm run dev

				
			

Important Points :

Tech Stack :

  • Frontend : Built using React JS.
  • Backend : Implemented with Node JS and Express.

Core Functionality :

  • Image Upload : Users can upload images through the React frontend.
  • Display : Uploaded images are displayed in the frontend interface.
  • The backend API is responsible for handling image uploads.

Possible Expansion :

  • Image validation.
  • Filtering features.
  • Frontend-Backend Interaction : The frontend communicates with the backend to manage image data.