
Security News
npm Adopts OIDC for Trusted Publishing in CI/CD Workflows
npm now supports Trusted Publishing with OIDC, enabling secure package publishing directly from CI/CD workflows without relying on long-lived tokens.
Frago is a reusable Django app that provides a secure, resumable, and parallel chunked file upload system. It supports large file uploads with resumable support, duplicate chunk detection, checksum verification, and customizable signal hooks — ideal for drone videos, media applications, and IoT devices.
pip install frago
Add frago to your Django INSTALLED_APPS:
# settings.py
INSTALLED_APPS = [
...
"frago",
]
Finally, run the following commands to create and apply the migrations:
python manage.py makemigrations frago
python manage.py migrate
you can confic these in settings.py
#🧠 How the uploader identifies the upload session
CHUNKED_UPLOADER_IDENTIFIER_MODE = "user"
Options: "anonymous" (default), "user"
You can override get_identifier() for custom logic.
# 📂 Where uploaded chunks are stored temporarily
CHUNKED_UPLOADER_CHUNK_UPLOAD_PATH = "chunked_uploads/"
# 📂 Where final assembled files go
CHUNKED_UPLOADER_ASSEMBLED_PATH = "assembled_videos/"
# 🔐 Hash type for file integrity checks
CHUNKED_UPLOADER_CHECKSUM_TYPE = "md5"
Any hashlib-supported algorithm (e.g., "sha256")
# ✅ Whether to perform checksum verification
CHUNKED_UPLOADER_DO_CHECKSUM = True
# ⏱️ Chunk expiration time (used for cleanup jobs)
CHUNKED_UPLOADER_EXPIRATION = timedelta(days=1)
# 📦 Read buffer size during assembly
CHUNKED_UPLOADER_ASSEMBLE_READ_SIZE = 8 * 1024 * 1024 # 8MB
# 🧱 Custom chunk model path (if overriding)
CHUNKED_UPLOADER_CHUNK_MODEL = "frago.ChunkedUploadChunk"
# 🧩 Custom upload model path (if overriding)
CHUNKED_UPLOADER_UPLOAD_MODEL = "frago.ChunkUpload"
1. Start a new upload
POST /upload/
Request:
{
"filename": "video.mp4",
"total_size": 104857600
}
Response:
{
"status": true,
"upload_id": "uuid4-string",
"message": "Upload started for video.mp4"
}
2. Upload a chunk
PUT /upload/{upload_id}/
Headers:
Content-Range: bytes 0-1048575/104857600
Body: multipart/form-data with key file and binary chunk data.
3. Finalize upload
POST /upload/{upload_id}/
Request
{
"checksum": "d41d8cd98f00b204e9800998ecf8427e",
"checksum_algo": "md5"
}
Response
{
"status": true,
"upload_id": "uuid4-string",
"message": "Upload completed for video.mp4"
}
4. Get upload status (only for authenticated users)
GET /upload/{upload_id}/
Or list uploads by current user/device:
GET /upload/
ChunkUpload
Tracks a single upload:
upload_id: UUID
filename, total_size
status: in_progress, complete, expired
created_at, completed_at
ChunkedUploadChunk
Tracks individual uploaded chunks:
start, end, size
Foreign key to ChunkUpload
Frago emits the following Django signals:
Signal Triggered When
upload_started : New upload is created
chunk_received : A chunk is received and saved
upload_completed : All chunks assembled, upload finalized
checksum_failed : Checksum mismatch during finalization
To extend behavior, connect signal handlers:
from frago.signals import upload_started
def my_handler(sender, upload, **kwargs):
print("Upload started:", upload.filename)
upload_started.connect(my_handler)
Add to your urls.py (if you are using with out any overides):
path('api/',include('frago.urls')),
Uploads expire after a period (EXPIRATION) and are marked expired.
Chunks and their metadata are deleted automatically on completion.
This is an example how you can overide and set your custome logic
By default, the view allows anonymous access. You should subclass the view and add authentication:
from rest_framework.permissions import IsAuthenticated
from rest_framework_simplejwt.authentication import JWTAuthentication
from frago.views import ParallelChunkedUploadView
class SecureUploadView(ParallelChunkedUploadView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
class MyView(ParallelChunkedUploadView):
authentication_classes = [CustomAuthentication]
identifier_field = 'device'
def get_identifier(self, request):
if self.IDENTIFIER_MODE == 'device':
device_id = request.user
if not device_id:
raise PermissionDenied("Device ID not found.")
try:
device = Devices.objects.get(inventory_id=device_id)
print('device',device.id)
return device # or another unique identifier
except Devices.DoesNotExist:
raise PermissionDenied("Invalid Device ID.")
# fallback to parent logic
return super().get_identifier(request)
Update your urls.py:
urlpatterns = [
path('upload/',MyView.as_view()),
path('upload/<uuid:pk>/', MyView.as_view()),
]
class Mychunkupload(AbstractChunkUpload):
device = models.ForeignKey(Devices,on_delete=models.CASCADE)
def assembled_path(self):
try:
device = Devices.objects.get(inventory_id=self.device_id)
base_path = device.videos or settings.ASSEMBLED_PATH
except Exception as e:
base_path = settings.ASSEMBLED_PATH
return os.path.join(base_path, f'{self.filename}')
Register it in settings:
CHUNKED_UPLOADER_UPLOAD_MODEL = 'fragotest.Mychunkupload'
and specify the identifier field in the view
identifier_field = 'device'
Use the official uploader client:
👉 frago-client
This project is licensed under the MIT License.
Pull requests are welcome!
Please open an issue first to discuss your idea.
Make sure to add tests for any new features or logic changes.
Built with ❤️ to support scalable file upload workflows in Django.
Let me know if you want:
Markdown preview badges
GitHub Actions/test coverage
Python client script (httpx/requests)
FAQs
Reusable Django app for resumable parallel chunked file uploads
We found that frago demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
npm now supports Trusted Publishing with OIDC, enabling secure package publishing directly from CI/CD workflows without relying on long-lived tokens.
Research
/Security News
A RubyGems malware campaign used 60 malicious packages posing as automation tools to steal credentials from social media and marketing tool users.
Security News
The CNA Scorecard ranks CVE issuers by data completeness, revealing major gaps in patch info and software identifiers across thousands of vulnerabilities.