a file upload progress bar with node (socket.io and formidable) and ajax

4 min read 07-10-2024
a file upload progress bar with node (socket.io and formidable) and ajax


Real-time File Upload Progress with Node.js, Socket.IO, Formidable, and AJAX

Problem: Implementing a real-time file upload progress bar in web applications can be challenging, especially when dealing with large files. Users need visual feedback on the upload process to ensure it's working as expected and avoid frustration.

Solution: This article will guide you through building a real-time file upload progress bar using Node.js, Socket.IO, Formidable, and AJAX. This approach provides a seamless user experience with constant updates on the upload progress.

Setting the Stage: The Scenario

Imagine a web application where users can upload files, such as images or documents. You want to display a visually appealing progress bar that updates in real-time as the file uploads.

Existing Code (Client-Side):

<form id="uploadForm" method="POST" enctype="multipart/form-data">
    <input type="file" id="fileInput">
    <button type="submit">Upload</button>
    <progress id="progressBar" value="0" max="100"></progress>
</form>

<script>
    const uploadForm = document.getElementById('uploadForm');
    const progressBar = document.getElementById('progressBar');

    uploadForm.addEventListener('submit', (event) => {
        event.preventDefault();
        // Handle file upload and update progress bar here
    });
</script>

Existing Code (Server-Side):

const express = require('express');
const formidable = require('formidable');
const app = express();

app.post('/upload', (req, res) => {
    const form = new formidable.IncomingForm();
    form.parse(req, (err, fields, files) => {
        if (err) {
            res.status(500).send(err);
        } else {
            // Handle file upload and response
        }
    });
});

app.listen(3000, () => console.log('Server listening on port 3000'));

This is a basic setup with a form, a progress bar, and server-side code to handle the upload request. However, it lacks real-time progress updates.

The Real-time Magic: Socket.IO and Formidable

To create the real-time progress bar, we'll use Socket.IO and Formidable.

Socket.IO: A library that enables real-time bidirectional communication between the server and client.

Formidable: A library that helps parse multipart/form-data requests, which are commonly used for file uploads.

Breakdown of the Solution

1. Server-Side Logic:

  • Socket.IO Server: Set up a Socket.IO server that listens for client connections.
  • Formidable: Use Formidable to parse incoming upload requests.
  • Progress Tracking: Calculate and emit progress updates via Socket.IO to the client.

2. Client-Side Logic:

  • Socket.IO Client: Connect to the Socket.IO server.
  • File Upload: Trigger the file upload using AJAX.
  • Progress Update: Listen for progress events from the server and update the progress bar accordingly.

Example Implementation (Server-Side):

const express = require('express');
const formidable = require('formidable');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);

app.post('/upload', (req, res) => {
    const form = new formidable.IncomingForm();
    form.parse(req, (err, fields, files) => {
        if (err) {
            res.status(500).send(err);
            return;
        }

        const file = files.file;
        const fileSize = file.size;
        let uploadedBytes = 0;

        const readStream = fs.createReadStream(file.path);
        readStream.on('data', (chunk) => {
            uploadedBytes += chunk.length;
            const progress = Math.round((uploadedBytes / fileSize) * 100);
            io.emit('uploadProgress', { progress });
        });

        readStream.on('end', () => {
            // File upload complete
            io.emit('uploadComplete');
        });
    });
});

io.on('connection', (socket) => {
    console.log('Client connected');
});

http.listen(3000, () => console.log('Server listening on port 3000'));

Example Implementation (Client-Side):

<form id="uploadForm" method="POST" enctype="multipart/form-data">
    <input type="file" id="fileInput">
    <button type="submit">Upload</button>
    <progress id="progressBar" value="0" max="100"></progress>
</form>

<script>
    const uploadForm = document.getElementById('uploadForm');
    const progressBar = document.getElementById('progressBar');

    const socket = io('http://localhost:3000');

    uploadForm.addEventListener('submit', (event) => {
        event.preventDefault();
        const fileInput = document.getElementById('fileInput');
        const file = fileInput.files[0];

        if (file) {
            const formData = new FormData();
            formData.append('file', file);

            const xhr = new XMLHttpRequest();
            xhr.open('POST', '/upload', true);
            xhr.upload.addEventListener('progress', (event) => {
                if (event.lengthComputable) {
                    const progress = Math.round((event.loaded / event.total) * 100);
                    progressBar.value = progress;
                }
            });

            socket.on('uploadProgress', (data) => {
                progressBar.value = data.progress;
            });

            socket.on('uploadComplete', () => {
                // Handle file upload completion
                console.log('Upload complete!');
            });

            xhr.send(formData);
        }
    });
</script>

Explanation:

  • The server-side code uses Formidable to handle the file upload and Socket.IO to emit progress updates.
  • The client-side code connects to the Socket.IO server, listens for progress events, and updates the progress bar accordingly.

Benefits of Real-Time Progress

  • User Experience: Real-time progress updates provide a smoother and more engaging user experience.
  • Error Handling: It helps identify and handle potential upload errors early on.
  • Large File Support: The solution scales well for large files.

Additional Considerations:

  • Security: Implement appropriate security measures like file size limits and file type validation.
  • Error Handling: Handle potential errors during file upload and provide informative error messages to the user.
  • Styling: Customize the progress bar's appearance to match your application's design.

Conclusion

By utilizing the power of Socket.IO, Formidable, and AJAX, you can create a robust real-time file upload progress bar that enhances the user experience and streamlines file uploads in your web application.

This article provides a starting point, and you can adapt the code and functionalities based on your specific requirements.

Further Exploration:

By implementing real-time progress updates, you can elevate the user experience of your web application, making file uploads more transparent and efficient.