HTML5 file uploading with multiple progress bars

HTML5 provides native file upload capabilities with progress tracking. When uploading multiple files, you can create individual progress bars for each file by leveraging the XMLHttpRequest progress events.

The Challenge

The main challenge is associating each XMLHttpRequest with its corresponding progress bar element. This requires storing a reference to the list item in the XMLHttpRequest object.

Setting Up the Progress Tracking

To track progress for multiple files, you need to bind each XMLHttpRequest to its corresponding list item element before starting the upload:

<!DOCTYPE html>
<html>
<head>
    <title>Multiple File Upload with Progress</title>
    <style>
        .file-item {
            margin: 10px 0;
            padding: 10px;
            border: 1px solid #ccc;
        }
        .progressbar {
            width: 0%;
            height: 20px;
            background-color: #4CAF50;
            transition: width 0.3s;
        }
        .progress-container {
            width: 100%;
            height: 20px;
            background-color: #f0f0f0;
            border-radius: 3px;
        }
    </style>
</head>
<body>
    <input type="file" id="fileInput" multiple>
    <button onclick="uploadFiles()">Upload Files</button>
    <div id="fileList"></div>

    <script>
        function uploadFiles() {
            const files = document.getElementById('fileInput').files;
            const fileList = document.getElementById('fileList');
            
            for (let i = 0; i < files.length; i++) {
                const file = files[i];
                
                // Create list item for each file
                const li = document.createElement('div');
                li.className = 'file-item';
                li.innerHTML = `
                    <div>${file.name}</div>
                    <div class="progress-container">
                        <div class="progressbar"></div>
                    </div>
                `;
                fileList.appendChild(li);
                
                // Create XMLHttpRequest and bind to list item
                const xhr = new XMLHttpRequest();
                xhr.upload.li = li;  // Store reference to list item
                
                // Set up progress event listener
                xhr.upload.addEventListener('progress', function(e) {
                    if (e.lengthComputable) {
                        const percentComplete = parseInt(e.loaded / e.total * 100);
                        this.li.querySelector('.progressbar').style.width = percentComplete + '%';
                    }
                }, false);
                
                // Handle upload completion
                xhr.addEventListener('load', function() {
                    this.upload.li.querySelector('.progressbar').style.backgroundColor = '#4CAF50';
                    console.log('Upload completed for:', file.name);
                });
                
                // Handle errors
                xhr.addEventListener('error', function() {
                    this.upload.li.querySelector('.progressbar').style.backgroundColor = '#f44336';
                    console.log('Upload failed for:', file.name);
                });
                
                // Start the upload
                const formData = new FormData();
                formData.append('file', file);
                xhr.open('POST', '/upload');
                xhr.send(formData);
            }
        }
    </script>
</body>
</html>

Key Implementation Points

The critical part is binding the list item reference to the XMLHttpRequest upload object:

<script>
// Create XMLHttpRequest and store reference
var xhr = new XMLHttpRequest();
xhr.upload.li = li;  // Bind list item to xhr

// Progress event can now access the correct element
xhr.upload.addEventListener('progress', function(e) {
   var percentComplete = parseInt(e.loaded / e.total * 100);
   this.li.querySelector(".progressbar").style.width = percentComplete + "%";
}, false);
</script>

How It Works

When the progress event fires, this refers to the xhr.upload object. Since we stored the list item reference as xhr.upload.li, we can access it through this.li and update the correct progress bar.

Browser Compatibility

This approach works in all modern browsers that support HTML5 file uploads and XMLHttpRequest Level 2. The progress events are well-supported across Chrome, Firefox, Safari, and Edge.

Conclusion

By storing a reference to each list item in its corresponding XMLHttpRequest object, you can easily track individual file upload progress. This technique ensures each progress bar updates correctly for its associated file.

Updated on: 2026-03-15T23:18:59+05:30

475 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements