In this post we discuss how to implement a file upload progress bar using JavaScript’s API with the FormData object. This approach allows for the same real-time progress tracking while keeping things simpler and more modern.
Add a <progress> element for visual feedback.
Use JavaScript's fetch API to handle the file upload and track progress.
<!-- HTML Form --> <form id="uploadForm" method="post" enctype="multipart/form-data" action="{% url 'upload_view' %}"> {% csrf_token %} {{ form.as_p }} <button type="submit">Upload</button> </form> <!-- Progress Bar --> <progress id="progressBar" value="0" max="100" style="width: 100%; display: none;"></progress> <span id="progressText"></span> <script> const form = document.getElementById("uploadForm"); const progressBar = document.getElementById("progressBar"); const progressText = document.getElementById("progressText"); form.onsubmit = function (event) { event.preventDefault(); // Prevent default form submission const formData = new FormData(form); // Get the CSRF token from the form const csrfToken = form.querySelector("[name=csrfmiddlewaretoken]").value; // Show progress bar progressBar.style.display = "block"; // Use XMLHttpRequest to upload the file with progress tracking const xhr = new XMLHttpRequest(); xhr.open("POST", form.action, true); xhr.setRequestHeader("X-CSRFToken", csrfToken); // Track upload progress xhr.upload.onprogress = function (event) { if (event.lengthComputable) { const percentComplete = (event.loaded / event.total) * 100; progressBar.value = percentComplete; progressText.textContent = `${Math.round(percentComplete)}% uploaded`; } }; // Handle the response xhr.onload = function () { if (xhr.status === 200) { // Reset progress bar and display success message alert("File uploaded successfully!"); progressBar.style.display = "none"; progressText.textContent = ""; // Redirect to the success URL window.location.href = "/album/"; // Use the success URL from your Django view context } else { alert("Error uploading file"); } }; // Handle any network errors xhr.onerror = function () { alert("An error occurred while uploading the file."); }; // Send the form data xhr.send(formData); }; </script>
Adjust the Django View to Handle the POST Request
This view receives the uploaded file data, validates it, and saves it if valid. The view then returns a JSON response indicating success or failure.
from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt @csrf_exempt # Only if CSRF tokens aren’t working with fetch API def upload_view(request): if request.method == "POST": form = YourUploadForm(request.POST, request.FILES) if form.is_valid(): form.save() # Save the file return JsonResponse({"status": "success"}) else: return JsonResponse({"status": "error", "errors": form.errors}, status=400) return JsonResponse({"status": "error", "message": "Invalid request"}, status=400)
Explanation
- XMLHttpRequest: This allows tracking upload progress, unlike fetch.
- Set CSRF Token: The X-CSRFToken header is set explicitly in the XMLHttpRequest for Django’s CSRF protection.
- Track Progress: The xhr.upload.onprogress event is used to update the progress bar and display the upload percentage.
Summary
This code should provide a working upload progress bar that accurately reflects the upload status of large files. With this setup, the progress bar should update correctly during the file upload.