Keywords: jQuery | AJAX | File Upload
Abstract: This article explores technical solutions for implementing file upload progress monitoring in modern web applications. By analyzing native XMLHttpRequest progress events, the FormData API, and integration with server-side modules like Nginx HttpUploadProgressModule, it provides a complete, cross-browser compatible implementation. The paper details how to avoid common iframe and plugin compatibility issues and demonstrates asynchronous file handling via AJAX, including support for multiple file uploads. Key topics include file selection listening, progress event handling, FormData construction, and server response parsing, offering practical insights for developers.
Introduction and Problem Context
In modern web development, file upload functionality is a core requirement for many applications, with users increasingly expecting real-time progress feedback. Traditional form-based uploads lack progress monitoring, leading to poor user experience. With the advent of HTML5 File API and XMLHttpRequest Level 2, implementing file uploads with progress tracking via AJAX has become feasible. However, challenges remain in cross-browser compatibility and integration with server modules like Nginx HttpUploadProgressModule. Based on common issues in practical development, this article presents a comprehensive solution.
Technical Core: XMLHttpRequest and File API
The key to AJAX file upload progress monitoring lies in utilizing native JavaScript's XMLHttpRequest object and HTML5 File API. Below is a basic example demonstrating file selection listening and upload:
<input id="files" type="file" />
<script>
document.getElementById('files').addEventListener('change', function(e) {
var file = this.files[0];
var xhr = new XMLHttpRequest();
(xhr.upload || xhr).addEventListener('progress', function(e) {
var done = e.position || e.loaded;
var total = e.totalSize || e.total;
console.log('xhr progress: ' + Math.round(done/total*100) + '%');
});
xhr.addEventListener('load', function(e) {
console.log('xhr upload complete', e, this.responseText);
});
xhr.open('post', '/upload-url', true);
xhr.send(file);
});
</script>This code uses addEventListener to listen for the change event on a file input, retrieving the user-selected file object. The XMLHttpRequest's upload property provides progress event listening, accommodating different browser property names (e.g., position vs. loaded). The file is sent directly via xhr.send(file), where file is of type Blob, adhering to the W3C File API standard.
Advanced Solution: Utilizing FormData API
While direct file sending works, using the FormData API better simulates traditional form submissions, supporting multiple files and additional form data. Example code:
var fd = new FormData();
fd.append('photo1', file);
fd.append('photo2', file2);
fd.append('other_data', 'foo bar');
xhr.send(fd);FormData allows developers to add files and other data as key-value pairs, simplifying server-side processing and improving compatibility. For instance, in PHP, uploaded files and additional data can be easily accessed via $_FILES and $_POST.
Cross-Browser Compatibility Handling
Early solutions often relied on jQuery plugins or iframes, which could cause compatibility issues, such as Uncaught ReferenceError: progressFrame is not defined in Chrome and Safari. The native method recommended here is based on modern browser standards, supporting major browsers like Chrome 8+ and Firefox 4+. For older IE versions, fallback solutions or polyfills can be considered, while maintaining core logic consistency.
Server-Side Integration: Nginx HttpUploadProgressModule
Integration with Nginx HttpUploadProgressModule requires proper server configuration. This module tracks upload requests to provide progress information, which the front-end can retrieve via polling or WebSocket. In AJAX uploads, combining FormData for data sending, a server-side script (e.g., PHP) handles as follows:
if ( isset($_FILES['file']) ) {
$filename = basename($_FILES['file']['name']);
$error = true;
if ( isset($_SERVER['WINDIR']) ) { // Example condition
$path = 'uploads/' . $filename;
$error = !move_uploaded_file($_FILES['file']['tmp_name'], $path);
}
$rsp = array(
'error' => $error,
'filename' => $filename,
'filepath' => '/uploads/' . $filename
);
echo json_encode($rsp);
exit;
}This code checks for uploaded files, moves them to a specified directory, and returns a JSON response for front-end completion event handling.
Multiple File Upload Implementation
Extending single-file upload to support multiple files involves modifying the file input with a multiple attribute and iterating over the files array:
<input id="files" type="file" multiple />
<script>
document.getElementById('files').addEventListener('change', function(e) {
var files = this.files;
var fd = new FormData();
for (var i = 0; i < files.length; i++) {
fd.append('file' + i, files[i]);
}
// Similar to single-file logic, send fd via xhr
});
</script>By looping to add multiple files to FormData, the server-side can iterate through them for batch upload processing.
Conclusion and Best Practices
This article details a native technology-based solution for file upload progress monitoring, avoiding plugin dependencies and iframe issues. Key steps include: listening for file selection, monitoring progress with XMLHttpRequest, optimizing data sending with FormData, and integrating server modules for processing. In practical projects, it is recommended to add error handling, user interface feedback (e.g., progress bars), and security validations (e.g., file type checks). This solution is compatible with major browsers, enhances user experience, and is applicable to various web application scenarios.