File Uploads and client_max_body_size
Introduction
Uploads through Nginx—forms, images, CSV imports—hit client_max_body_size before your Spring Boot or Node app sees the file. Timeouts and buffering matter too. This chapter aligns Nginx limits with backend multipart settings for reliable uploads.
Prerequisites
- Reverse Proxy Basics
- Nginx Troubleshooting Guide (413 errors)
Default Body Size Limit
Nginx default is often 1 MB. Larger uploads return 413 Request Entity Too Large without reaching your app.
http {
client_max_body_size 50M;
}Or per site / location:
server {
listen 443 ssl;
server_name api.example.com;
client_max_body_size 100M;
location /api/upload {
proxy_pass http://127.0.0.1:8080;
include /etc/nginx/proxy_params;
}
}Code explanation:
50Maccepts bodies up to 50 megabytes- Use
0to disable size check (not recommended—DoS risk)
Reload after change:
sudo nginx -t && sudo systemctl reload nginxAlign Spring Boot
application.properties:
spring.servlet.multipart.max-file-size=50MB
spring.servlet.multipart.max-request-size=50MB
server.tomcat.max-swallow-size=-1Code explanation:
- Nginx limit should be ≥ Spring limits
- If Nginx allows 100M but Spring allows 10M, app rejects at 10M
Align Node / Express
const express = require("express");
const app = express();
app.use(express.json({ limit: "50mb" }));
app.use(express.urlencoded({ limit: "50mb", extended: true }));For multer, set limits.fileSize consistently.
Upload Timeouts
Slow mobile uploads need longer proxy timeouts:
location /api/upload {
client_max_body_size 100M;
proxy_pass http://127.0.0.1:8080;
include /etc/nginx/proxy_params;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
client_body_timeout 300s;
}Code explanation:
client_body_timeout— max time to receive body from clientproxy_send_timeout— max time to send body to upstream
504 during large upload often means raise these values or optimize storage I/O on backend.
client_body_buffer_size
Small uploads buffered in memory; large spill to disk:
client_body_buffer_size 128k;
client_body_temp_path /var/lib/nginx/body;Ensure temp path exists and disk has space (df -h).
Direct Static Upload to Disk (Rare)
Nginx upload module is third-party—not in default packages. Most apps accept multipart in Spring/Node; Nginx only proxies.
Testing Upload Limit
dd if=/dev/zero of=/tmp/test.bin bs=1M count=60
curl -F "file=@/tmp/test.bin" https://api.example.com/api/uploadExpect 413 when over limit; 200 or app validation error when within limits.
Security Notes
- Cap size to business need—do not set 1G “just because”
- Scan uploads in app layer; Nginx does not antivirus by default
- Rate limit upload endpoints—see rate limiting chapter
FAQ
413 but size seems small?
Check nested location—child may inherit or override client_max_body_size.
multipart/form-data through proxy?
Works with default buffering; tune timeouts for big files.
Chunked transfer encoding?
Generally supported; size limit still applies to total body.
Resume / tus protocol?
Large resumable uploads need app support—Nginx is passive proxy.
Two limits which wins?
Stricter of Nginx vs app wins first—align both intentionally.
CDN upload size?
CDN may have separate limit before request hits origin Nginx.