REST API Multipart File Upload Example
This REST API file upload example uses multipart/form-data because the request carries file bytes plus metadata, while the server still controls authorization, size limits, type validation, storage and post-upload scanning.
multipart/form-data is a standard choice when one request carries a file plus additional form fields. RFC 7578 defines the multipart format used by HTML forms and many API clients.
POST /v1/documents HTTP/1.1
Authorization: Bearer <token>
Content-Type: multipart/form-data; boundary=----upload-123
------upload-123
Content-Disposition: form-data; name="file"; filename="invoice.pdf"
Content-Type: application/pdf
<binary file bytes>
------upload-123--The server should treat the supplied filename and per-part Content-Type as untrusted metadata. Validate the actual file against your allowlist and business requirements before making it available.
REST API File Upload with Metadata
When the upload needs structured metadata, use a dedicated JSON part rather than encoding an unbounded number of form fields:
POST /v1/documents HTTP/1.1
Content-Type: multipart/form-data; boundary=----upload-456
------upload-456
Content-Disposition: form-data; name="metadata"
Content-Type: application/json
{"document_type":"invoice","customer_id":"cus_42","tags":["finance","2026"]}
------upload-456
Content-Disposition: form-data; name="file"; filename="invoice.pdf"
Content-Type: application/pdf
<binary file bytes>
------upload-456--Validate metadata and file content independently. The metadata must not be allowed to choose arbitrary filesystem paths, storage buckets, processing commands or authorization scope.
REST API File Upload Size Limits
There is no universal correct upload size. Set limits from the business use case and enforce them at every layer that can consume resources: CDN/load balancer, reverse proxy, API gateway, application server and storage workflow.
| Control | Example decision | Why |
|---|---|---|
| Maximum request size | 25 MB | Stops oversized request bodies before deep processing. |
| Maximum file count | 5 files | Prevents many tiny parts from bypassing a single-file limit. |
| Per-file size | 20 MB | Makes behavior predictable for each object. |
| Metadata size | 64 KB | Prevents an upload endpoint becoming an oversized JSON endpoint. |
| Processing timeout | Async after receipt | Avoids keeping an HTTP request open during AV/CDR/transcoding. |
OWASP recommends defining file-size limits as part of a secure upload implementation. Oversized requests can also be rejected with the appropriate request-size status supported by your HTTP stack.
HTTP defines 413 Content Too Large for a request whose content exceeds the server’s limit. Rejecting early at the edge or reverse proxy is preferable to buffering an oversized upload in application memory first.
A Secure File Upload Validation Workflow
- Authenticate the user and authorize the upload action before accepting the file into the normal processing path.
- Enforce request and file-size limits as early as possible.
- Allowlist the business-required extensions; normalize and validate filenames.
- Check file signatures/magic bytes and parse the file format where feasible; do not trust the client
Content-Typealone. - Generate a new internal storage name or object key instead of storing under the user-supplied filename.
- Run malware scanning and, where applicable, content disarm/reconstruction or specialized parsers.
- Keep untrusted files quarantined until validation finishes.
- Store outside the web root or on a separate object-storage origin and control download authorization explicitly.
File Storage and Download Design
Application-proxied upload
Client uploads to the API, which enforces policy and streams to storage. Simple contract, but application servers handle every byte.
Direct object-storage upload
API authorizes the operation and issues a short-lived upload URL; client uploads directly to storage. Better for large files, but you still need post-upload validation, ownership binding and finalization.
For direct uploads, do not treat possession of an upload URL as permanent authorization. Bind the object key to the authenticated principal and expected size/type, use short expirations, and require the application to finalize or validate the object before it becomes trusted.
Direct-to-Storage Finalization Pattern
POST /v1/uploads
→ create upload_id + short-lived storage instructions
PUT <signed-storage-url>
→ upload bytes directly
POST /v1/uploads/upl_123/complete
→ verify object, size, checksum, ownership and scan state
→ mark file availableThe finalization step prevents an object from becoming trusted merely because storage accepted the bytes. Keep the object quarantined or unavailable until server-side checks finish.
Large File Upload API Design
For large uploads, resumable or multipart object-storage workflows are usually more reliable than one giant application request. The API can create an upload session, return signed part URLs or upload instructions, then finalize the upload after all parts are present.
POST /v1/uploads
{ "filename": "video.mp4", "size": 734003200, "content_type": "video/mp4" }
201 Created
{ "upload_id": "upl_123", "status": "pending", "part_size": 10485760 }Do not skip final validation because parts arrived through trusted storage infrastructure. The file is still user-controlled content.
REST API File Upload Security Checklist
- Allow only extensions and formats required by the product.
- Validate type independently of the client-provided MIME header.
- Generate server-side filenames/object keys.
- Restrict filename length and characters if original names are retained as metadata.
- Set size and file-count limits.
- Require authorization for upload and download.
- Store outside the application web root or on a separate storage service.
- Scan or sanitize risky content before release.
- Protect archive extraction against path traversal and decompression bombs.
- Log upload identity, object ID, size, detected type and validation outcome without recording sensitive file content.
See also Ammune’s REST API endpoint security guidance for request validation and authorization controls.
Common File Upload API Mistakes
- Trusting
Content-Type: image/jpegwithout checking the file. - Saving files directly under their original filename.
- Allowing executable or active-content formats that the product does not need.
- Enforcing a limit only in application code after the entire body has already been buffered.
- Serving uploaded content from the same privileged origin without safe response headers.
- Scanning synchronously for minutes and holding the client connection open.
Multipart File Upload with cURL
A client can send a multipart file and JSON metadata without manually creating MIME boundaries:
curl -X POST https://api.example.com/v1/documents \
-H "Authorization: Bearer $TOKEN" \
-F 'metadata={"document_type":"invoice","customer_id":"cus_42"};type=application/json' \
-F 'file=@invoice.pdf;type=application/pdf'The server still decides whether a PDF is allowed and valid. Client tooling choosing application/pdf does not prove the bytes represent a safe PDF.
Serving Uploaded Files Safely
Upload security continues after storage. When a user later downloads or previews the object, return the correct content type, apply authorization again, and consider Content-Disposition: attachment for formats that should not execute in the application origin.
- Do not expose a predictable storage path that bypasses application authorization.
- Separate untrusted user content from the privileged application origin when possible.
- Preserve the original filename only as metadata and safely encode it when used in response headers.
- Set caching rules according to sensitivity; private documents should not become publicly cacheable.
- For image/document transformation, treat the parser/converter as another untrusted-input boundary and keep it patched/sandboxed.
For very large objects, direct-to-storage upload and download URLs can reduce application bandwidth, but signed URLs should be short-lived, scoped to one object and issued only after authorization.
How Ammune Fits
File uploads combine large request bodies, metadata, authorization and often asynchronous processing. Ammune can provide runtime visibility into upload endpoints, unusual request sizes, automation patterns and API abuse, complementing the application’s mandatory file-validation, malware-scanning and storage controls.
Production Implementation Checklist
- Define allowed file types from real product requirements.
- Enforce request, file-count and per-file size limits early.
- Do not trust filenames or client Content-Type values.
- Validate signatures/format using safe parsers.
- Generate internal storage keys server-side.
- Quarantine uploads until required scanning/processing completes.
- Store outside the application web root or on isolated object storage.
- Authorize both upload and later download.
- Protect archive extraction and transformation pipelines.
- Test oversized, malformed, spoofed and concurrent uploads.
Frequently Asked Questions
How do I upload a file in a REST API?
A common approach is a POST request using multipart/form-data, with the file in one part and optional metadata in another. Large files may be uploaded directly to object storage using an API-authorized upload session.
Should a REST API use multipart/form-data for file uploads?
Use multipart/form-data when a request needs one or more files plus form fields or metadata. For a single raw object, a direct binary body can also be valid if the API contract is clear.
How should file upload size limits be set?
Base limits on the real business requirement and enforce them at edge/proxy, application and storage layers. Also limit file count and metadata size so attackers cannot bypass a simple per-file limit.
Can I trust the Content-Type sent with an uploaded file?
No. The header is client-controlled and can be spoofed. Validate the file format using signatures, safe parsing and an allowlist appropriate to the application.
Where should uploaded files be stored?
Prefer storage outside the application web root or on a separate object-storage service. Generate internal object names and enforce authorization when files are downloaded.
Primary References
Protect High-Risk Upload APIs at Runtime
Secure upload processing starts with strict validation and storage design. Ammune adds visibility into how upload endpoints are used and abused in production.
