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

Default Body Size Limit

Nginx default is often 1 MB. Larger uploads return 413 Request Entity Too Large without reaching your app.

nginx
http {
    client_max_body_size 50M;
}

Or per site / location:

nginx
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:

  • 50M accepts bodies up to 50 megabytes
  • Use 0 to disable size check (not recommended—DoS risk)

Reload after change:

bash
sudo nginx -t && sudo systemctl reload nginx

Align Spring Boot

application.properties:

properties
spring.servlet.multipart.max-file-size=50MB
spring.servlet.multipart.max-request-size=50MB
server.tomcat.max-swallow-size=-1

Code explanation:

  • Nginx limit should be Spring limits
  • If Nginx allows 100M but Spring allows 10M, app rejects at 10M

Align Node / Express

javascript
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:

nginx
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 client
  • proxy_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:

nginx
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

bash
dd if=/dev/zero of=/tmp/test.bin bs=1M count=60
curl -F "file=@/tmp/test.bin" https://api.example.com/api/upload

Expect 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.