Handling File Uploads

1. Using Multipart Form Data

PropertyValue
Content-Typemultipart/form-data; boundary=...
Multiple fieldsMix files and text fields
Per-part headersContent-Disposition, Content-Type
MemoryStream to disk for large files

2. Implementing Chunked Uploads

Example: Tus Resumable Upload Protocol

# 1. Create upload
POST /uploads
Upload-Length: 10485760
Upload-Metadata: filename bWUucG5n
 201 Created
   Location: /uploads/abc-123

# 2. Upload chunks (resumable)
PATCH /uploads/abc-123
Upload-Offset: 0
Content-Type: application/offset+octet-stream
<binary chunk>
 204 No Content
   Upload-Offset: 524288

# 3. Resume after failure
HEAD /uploads/abc-123
 Upload-Offset: 524288 (resume from here)

3. Validating File Types

CheckMethod
ExtensionQuick filter, easy to spoof
MIME type (header)Client-supplied; verify
Magic bytesFirst N bytes of file (e.g. 89 50 4E 47 = PNG)
AllowlistWhitelist accepted types only

4. Implementing File Size Limits

LimitTypical
Per-file10-100 MB
Total request500 MB
Per-user quotaConfigurable
Over limit response413 Payload Too Large

5. Generating Presigned URLs

Client uploads directly to storage (S3, GCS, Azure Blob), bypassing API server.

Example: Presigned URL Flow

POST /uploads/presign
{"filename": "report.pdf", "contentType": "application/pdf", "size": 1048576}

 {
    "uploadUrl": "https://s3.amazonaws.com/...?X-Amz-Signature=...",
    "method": "PUT",
    "headers": {"Content-Type": "application/pdf"},
    "expiresIn": 900,
    "fileUrl": "https://cdn.example.com/files/abc123.pdf"
  }

# Client then PUTs file directly to S3

6. Handling Upload Progress Tracking

TechniqueNotes
XHR upload.onprogressBrowser-native byte tracking
Fetch + ReadableStreamModern; per-chunk progress
Tus protocolServer tracks Upload-Offset

7. Implementing Direct-to-Storage Uploads

BenefitTradeoff
Reduces API server loadCORS configuration on storage
Higher throughputPre/post-upload validation needs separate calls
Lower latencyTighter coupling to storage SDK

8. Validating File Content

CheckTool
Virus scanClamAV, VirusTotal
Image dimensionsPillow, sharp, ImageMagick
EXIF strippingRemove GPS/camera metadata
Office docs / PDFsSandboxed parsing; reject macros
SVG sanitizationStrip <script>, event handlers

9. Returning Upload Status

StatusBody
201 CreatedFile metadata + URL
202 AcceptedAsync processing (virus scan, transcoding)
413 Payload Too LargeFile over size limit
415 Unsupported Media TypeFile type not allowed

10. Handling Upload Errors

ErrorHandling
Network interruptionResume via Tus or chunked retry
Quota exceeded413 with quota info
Storage error500/503 + retry guidance
Virus detected422 + cleanup uploaded file