Open In App

React Single File Upload with Multer and Express.js

When we want to add functionality for uploading or deleting files, file storage becomes crucial, whether it’s for website or personal use. The File Storage project using Express aims to develop a web application that provides users with a secure and efficient way to store and manage their files online. With Express, we’ll be able to create a user-friendly application that allows you to upload, delete, and display your files hassle-free. Let’s get started on this exciting project!

Preview of Final Output:



Prerequisites and Technologies:



Approach:

We will be utilizing Express to develop the entire backend, while the Multer module will be used for file uploads. The application will include three routes: upload, delete, and view. The upload route will be used for file uploads, the delete route will be used for deleting specific files, and the view route will be used to display all files. The HTML page will be utilized to display all files, along with the options to upload and delete. The files will be stored on the server inside the /file storage folder, and the application will support all types of files.

 

Functionalities:

Steps to Create A Project:

Step 1: First we need to create react app using below command

npx create-react-app <<Project_Name>>

Step 2: Navigate to the folder

cd <<Project_Name>>

Step 3: Install the following packages using the below command.

npm install express multer ejs

Step 4: Now create app.js file in project folder. we will setup express application first create a express app instance. Configure app to use EJS. For EJS create /views folder inside project folder. This folder will consist our HTML code.

Project Structure:

Project Structure

The updated dependencies in package.json will look like this:

{
"name": "gfg-filestorage",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node app.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"ejs": "^3.1.9",
"express": "^4.18.2",
"multer": "^1.4.5-lts.1"
}
}

Example:




// app.js
const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
  
const app = express();
const port = 3000;
  
app.set('view engine', 'ejs');
  
app.set('views', path.join(__dirname, 'views'));
  
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'filestorage/');
  },
  filename: (req, file, cb) => {
    const fileName = `${Date.now()}-${file.originalname}`;
    cb(null, fileName);
  },
});
  
const upload = multer({ storage });
  
app.use('/uploads', express.static(path.join(__dirname, 'filestorage')));
  
app.get('/', (req, res) => {
  res.render('index')
});
  
app.post('/upload', upload.single('file'), (req, res) => {
    res.redirect('/')
});
  
app.delete('/delete/:fileName', (req, res) => {
  const fileName = req.params.fileName;
  const filePath = path.join(__dirname, 'filestorage', fileName);
  
  if (fs.existsSync(filePath)) {
    fs.unlinkSync(filePath);
    res.send(`File "${fileName}" has been deleted.`);
  } else {
    res.status(404).send(`File "${fileName}" not found.`);
  }
});
  
app.get('/view', (req, res) => {
  const uploadDirectory = path.join(__dirname, 'filestorage');
  fs.readdir(uploadDirectory, (err, files) => {
    if (err) {
      console.error(err);
      res.status(500).send('Error reading the upload directory.');
    } else {
      res.json({ files });
    }
  });
});
  
app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});




// index.ejs
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" 
          content="width=device-width, initial-scale=1.0">
    <title>File Storage App</title>
    <script src=
    </script>
    <script src=
    </script>
    <link href=
          rel="stylesheet">
  
    <link href=
          rel="stylesheet">
</head>
<body>
    <div class="container">
        <h1 class="mt-5 text-success">GeeksForGeeks File Storage</h1>
  
        <h2 class="mt-4">Upload File</h2>
        <form action="/upload" method="POST" 
              enctype="multipart/form-data">
            <div class="mb-3">
                <input type="file" name="file" 
                       class="form-control" required>
            </div>
            <button type="submit" class="btn btn-primary">Upload</button>
        </form>
  
        <h2 class="mt-4">Delete File</h2>
        <form id="deleteForm">
            <div class="mb-3">
                <select id="fileSelect" name="fileName"
                        class="form-select">
                </select>
            </div>
            <button type="button" class="btn btn-danger" 
                    onclick="deleteFile()">Delete</button>
        </form>
  
        <h2 class="mt-4">Uploaded Files</h2>
        <ul id="fileList" class="list-group">
        </ul>
    </div>
  
  
  
    <script>
        function populateFileListWithIcons() {
            fetch('/view')
                .then(response => response.json())
                .then(data => {
                    const fileList = document.getElementById('fileList');
                    fileList.innerHTML = '';
  
                    data.files.forEach(fileName => {
                        const listItem = document.createElement('li');
      listItem.className = 'list-group-item d-flex justify-content-between align-items-center';
  
                        const fileExtension = fileName.split('.').pop();
  
                        const iconSpan = document.createElement('span');
                        iconSpan.className = 'me-3';
                        iconSpan.innerHTML = getFileIconHTML(fileExtension);
  
                        const fileLink = document.createElement('a');
                        fileLink.href = `/uploads/${fileName}`;
                        fileLink.textContent = fileName;
  
                        listItem.appendChild(iconSpan);
                        listItem.appendChild(fileLink);
  
                        fileList.appendChild(listItem);
                    });
                })
                .catch(error => console.error(error));
        }
  
        function getFileIconHTML(fileExtension) {
            const iconClasses = {
                pdf: 'far fa-file-pdf',
                doc: 'far fa-file-word',
                docx: 'far fa-file-word',
                xls: 'far fa-file-excel',
                xlsx: 'far fa-file-excel',
                ppt: 'far fa-file-powerpoint',
                pptx: 'far fa-file-powerpoint',
                txt: 'far fa-file-alt',
                jpg: 'far fa-file-image',
                jpeg: 'far fa-file-image',
                png: 'far fa-file-image',
                gif: 'far fa-file-image',
                default: 'far fa-file'
            };
  
          return `<i class="${iconClasses[fileExtension.toLowerCase()] || iconClasses['default']}">
      </i>`;
        }
  
        function deleteFile() {
            const deleteForm = document.getElementById('deleteForm');
            const formData = new FormData(deleteForm);
  
            fetch(`/delete/${formData.get('fileName')}`, {
                method: 'DELETE',
            })
                .then(response => response.text())
                .then(message => {
                    alert(message);
                    populateFileListWithIcons();
                    populateDeleteOptions();
                })
                .catch(error => console.error(error));
        }
  
        function populateDeleteOptions() {
            fetch('/view')
                .then(response => response.json())
                .then(data => {
                    const fileSelect = document.getElementById('fileSelect');
                    fileSelect.innerHTML = '';
                    data.files.forEach(fileName => {
                        const option = document.createElement('option');
                        option.value = fileName;
                        option.textContent = fileName;
                        fileSelect.appendChild(option);
                    });
                })
                .catch(error => console.error(error));
        }
  
        populateFileListWithIcons();
        populateDeleteOptions();
    </script>
</body>
</html>

Steps to Run the application:

Step 1. Type the following command in terminal.

npm start

Step 2. Open web-browser and type the following URL

http://localhost:3000/

Output:


Article Tags :