This document provides a comprehensive guide to handling file uploads in the sillo framework, covering both single and multiple file upload scenarios with proper validation and security considerations.
File Uploads
Section titled “File Uploads”Single File Upload
Section titled “Single File Upload”To handle a single file upload in sillo:
from sillo import HttpContext, json
@app.post("/upload")async def upload_file(ctx: HttpContext): files = await ctx.files if not files: return json({"error": "No files uploaded"}).status(400)
file = files["file"] # 'file' is the field name in the form file_content = await file.read()
# Save file or process it # ...
return {"filename": file.filename, "size": len(file_content)}Multiple File Uploads
Section titled “Multiple File Uploads”For handling multiple files from the same field:
from sillo import HttpContext, json
@app.post("/uploads")async def upload_files(ctx: HttpContext): files = await ctx.files if not files: return json({"error": "No files uploaded"}).status(400)
results = [] for file in files.getlist("files"): # 'files' is the field name file_content = await file.read() # Process each file results.append({ "filename": file.filename, "size": len(file_content) })
return {"files": results}Security Considerations
Section titled “Security Considerations”File Type Validation
Section titled “File Type Validation”Validate file extensions and MIME types:
from sillo import HttpContext, json
ALLOWED_EXTENSIONS = {"jpg", "jpeg", "png", "gif"}ALLOWED_MIME_TYPES = {"image/jpeg", "image/png", "image/gif"}
@app.post("/upload-image")async def upload_image(ctx: HttpContext): files = await ctx.files if not files: return json({"error": "No file uploaded"}).status(400)
file = files["image"]
# Validate extension file_ext = file.filename.split(".")[-1].lower() if file_ext not in ALLOWED_EXTENSIONS: return json({"error": "Invalid file type"}).status(400)
# Validate MIME type if file.content_type not in ALLOWED_MIME_TYPES: return json({"error": "Invalid MIME type"}).status(400)
# Process valid file # ...Form Data with Files
Section titled “Form Data with Files”Handle mixed form data and file uploads:
from sillo import HttpContext
@app.post("/profile")async def update_profile(ctx: HttpContext): form_data = await ctx.form files = await ctx.files
name = form_data.get("name") avatar = files.get("avatar")
if avatar: avatar_content = await avatar.read() # Save avatar # ...
return {"name": name, "avatar_uploaded": bool(avatar)}Advanced Configuration
Section titled “Advanced Configuration”Custom Upload Handlers
Section titled “Custom Upload Handlers”Create middleware for file upload processing:
from sillo import HttpContext
async def file_upload_middleware(ctx: HttpContext, call_next): if ctx.method == "POST" and "multipart/form-data" in ctx.headers.get("Content-Type", ""): # Pre-process uploads ctx.state.upload_dir = "/path/to/uploads"
return await call_next()
app.use(file_upload_middleware)Streaming Large Files
Section titled “Streaming Large Files”For handling very large files without memory issues:
from sillo import HttpContext, json
@app.post("/upload-large")async def upload_large_file(ctx: HttpContext): files = await ctx.files file = files.get("file")
if not file: return json({"error": "No file uploaded"}).status(400)
# Process in chunks chunk_size = 1024 * 1024 # 1MB chunks total_size = 0
async with open(f"/uploads/{file.filename}", "wb") as f: while True: chunk = await file.read(chunk_size) if not chunk: break await f.write(chunk) total_size += len(chunk)
return { "filename": file.filename, "size": total_size, "status": "uploaded" }Troubleshooting
Section titled “Troubleshooting”Common issues and solutions:
-
File size too large:
- Increase
max_file_sizein config - Use streaming for very large files
- Increase
-
Memory errors:
- Process files in chunks
- Use
ctx.stream()for direct access to the upload stream
-
File validation failures:
- Always check both filename extension and MIME type
- Consider scanning uploaded files for malware
Best Practices
Section titled “Best Practices”- Always validate file types and sizes
- Never trust original filenames - sanitize or generate new ones
- Store files outside web root when possible
- Set appropriate permissions on upload directories
- Consider virus scanning for user uploads
- Use CSRF protection for upload forms
This documentation covers the essential aspects of file upload handling in the sillo framework. For more advanced scenarios, refer to the framework’s multipart parsing and streaming capabilities.