Works with any backend npm install Zero dependencies

Django

Handle MultipleUpload file uploads with Django using request.FILES and function-based views. This guide covers both standard multipart uploads and chunked uploads.

Dependencies

pip install django django-cors-headers

Settings

Add CORS support in settings.py.

# settings.py
INSTALLED_APPS = [
 # ...
 "corsheaders",
]

MIDDLEWARE = [
 "corsheaders.middleware.CorsMiddleware",
 # ... other middleware
]

CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_HEADERS = [
 "content-type", "x-upload-id", "x-chunk-index",
 "x-chunk-count", "x-file-name", "x-file-size",
]

FILE_UPLOAD_MAX_MEMORY_SIZE = 200 * 1024 * 1024 # 200 MB
DATA_UPLOAD_MAX_MEMORY_SIZE = 200 * 1024 * 1024

URL Configuration

# urls.py
from django.urls import path
from . import views

urlpatterns = [
 path("api/upload", views.upload_file, name="upload"),
 path("api/upload-chunk", views.upload_chunk, name="upload_chunk"),
]

Multipart Form Upload

The view receives the file through Django's request.FILES dictionary and saves it with a unique GUID.

# views.py
import os
import uuid
import shutil
import json
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.conf import settings

UPLOAD_DIR = os.path.join(settings.BASE_DIR, "uploads")
CHUNK_DIR = os.path.join(UPLOAD_DIR, "chunks")
os.makedirs(UPLOAD_DIR, exist_ok=True)


@csrf_exempt
@require_POST
def upload_file(request):
 uploaded_file = request.FILES.get("file")
 if not uploaded_file:
 return JsonResponse({"success": False, "error": "No file uploaded"}, status=400)

 file_guid = str(uuid.uuid4())
 ext = os.path.splitext(uploaded_file.name)[1]
 dest_path = os.path.join(UPLOAD_DIR, file_guid + ext)

 with open(dest_path, "wb") as dest:
 for chunk in uploaded_file.chunks():
 dest.write(chunk)

 return JsonResponse({
 "success": True,
 "fileGuid": file_guid,
 "fileName": uploaded_file.name,
 "fileSize": uploaded_file.size,
 })

Chunked Upload

Each chunk arrives as a raw body with custom headers. Store chunks in a temporary directory and assemble the final file once all chunks have arrived.

@csrf_exempt
@require_POST
def upload_chunk(request):
 upload_id = request.headers.get("X-Upload-Id", "")
 chunk_index = int(request.headers.get("X-Chunk-Index", 0))
 chunk_count = int(request.headers.get("X-Chunk-Count", 0))
 file_name = request.headers.get("X-File-Name", "unknown")
 file_size = int(request.headers.get("X-File-Size", 0))

 if not upload_id or not chunk_count:
 return JsonResponse({"success": False, "error": "Missing headers"}, status=400)

 session_dir = os.path.join(CHUNK_DIR, upload_id)
 os.makedirs(session_dir, exist_ok=True)

 # Save this chunk from raw body
 chunk_path = os.path.join(session_dir, f"chunk_{chunk_index}")
 with open(chunk_path, "wb") as f:
 f.write(request.body)

 # Count received chunks
 received = len([
 name for name in os.listdir(session_dir)
 if name.startswith("chunk_")
 ])

 if received == chunk_count:
 # Assemble final file
 file_guid = str(uuid.uuid4())
 ext = os.path.splitext(file_name)[1] if file_name else ""
 final_path = os.path.join(UPLOAD_DIR, file_guid + ext)

 with open(final_path, "wb") as output:
 for i in range(chunk_count):
 cp = os.path.join(session_dir, f"chunk_{i}")
 with open(cp, "rb") as chunk_file:
 output.write(chunk_file.read())

 # Clean up chunks
 shutil.rmtree(session_dir)

 return JsonResponse({
 "success": True,
 "fileGuid": file_guid,
 "fileName": file_name,
 "fileSize": file_size,
 })

 return JsonResponse({"success": True, "chunksReceived": received})

Expected JSON Response

Both endpoints must return this JSON structure on successful upload completion.

{
 "success": true,
 "fileGuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
 "fileName": "photo.jpg",
 "fileSize": 204800
}

Client-Side JavaScript

Initialize MultipleUpload on the client, pointing to your Django endpoints.

<link rel="stylesheet" href="multipleupload.css" />
<div id="uploader"></div>
<script src="multipleupload.js"></script>
<script>
 var uploader = new MultipleUpload("#uploader", {
 uploadUrl: "/api/upload",
 chunkUploadUrl: "/api/upload-chunk",
 chunkSize: 2 * 1024 * 1024, // 2 MB chunks
 onFileUploaded: function (file, response) {
 console.log("Uploaded:", response.fileName, response.fileGuid);
 }
 });
</script>