Nginx代理下1GB文件上传400错误问题排查求助
Hey there, let's dig into this frustrating large file upload issue you're facing. That 400 error at 99% with the client prematurely closed connection log is usually a sign of a timeout or resource mismatch somewhere in the chain—let's break down the fixes step by step, using your existing Nginx config as a starting point.
1. Fill in Missing Timeout Configurations
Your current Nginx config has some timeouts set, but you're missing a critical one that could cause premature disconnections during long uploads:
- Add
proxy_connect_timeout 50m;to yourserverblock (orhttpblock for global effect). This ensures Nginx doesn't give up trying to connect to the Sails backend too early. - Double-check your frontend AngularJS code: The
$httpservice has a default timeout that might be cutting off the upload before it finishes. Update your upload request to include a longer timeout, like:$http.post('/test/upload', formData, { timeout: 50 * 60 * 1000 // 50 minutes, matching your Nginx settings });
2. Optimize Nginx Client Body Handling
Your client_body_buffer_size is set to 2048M, which is way too large—this forces Nginx to try caching the entire 1GB file in memory instead of writing it to disk immediately, which can cause memory pressure and unexpected disconnects. Adjust these settings in your /test/upload location:
location /test/upload { proxy_send_timeout 50m; proxy_read_timeout 50m; proxy_pass http://api; # ... keep your existing proxy headers ... client_body_in_file_only clean; client_body_buffer_size 64K; # Small buffer to push data to disk quickly client_body_temp_path /tmp/nginx_uploads; # Use a dedicated temp dir client_max_body_size 2048M; }
- Make sure the
client_body_temp_pathdirectory exists and is writable by thewww-datauser:mkdir -p /tmp/nginx_uploads chown www-data:www-data /tmp/nginx_uploads
3. Update Sails.js Upload & Timeout Settings
Don't forget the backend! Sails uses the skipper middleware for file uploads, which has its own limits:
- In your Sails project's
config/http.js, adjust theskipperbody parser to allow large files:module.exports.http = { middleware: { bodyParser: require('skipper')({ maxBytes: 2 * 1024 * 1024 * 1024 // 2GB, match Nginx's client_max_body_size }) } }; - Add a server timeout to prevent Sails from closing the connection early. In
config/local.js(orconfig/http.js):module.exports = { serverTimeout: 50 * 60 * 1000 // 50 minutes };
4. Check Network & System-Level Limits
- Firewall/Proxy/CDN: If you're using a firewall, reverse proxy, or CDN between the frontend and Nginx, verify that it doesn't have a shorter upload timeout limit. Adjust those settings to match your 50-minute window.
- Linux TCP Settings: Tweak your system's TCP keepalive settings to prevent idle connections from being dropped:
# Temporary fix (resets on reboot) sysctl -w net.ipv4.tcp_fin_timeout=300 sysctl -w net.ipv4.tcp_keepalive_time=1200 # Permanent fix: Add these lines to /etc/sysctl.conf net.ipv4.tcp_fin_timeout=300 net.ipv4.tcp_keepalive_time=1200
5. If You Want to Re-enable the Nginx Upload Module
If you decide to go back to the ngx_http_upload_module, fix these gaps in your commented-out config:
- Ensure the
/tmpdirectory has subdirectories0-9(required for the hashed storage):for i in {0..9}; do mkdir -p /tmp/$i; done chown -R www-data:www-data /tmp - Make sure the
upload_pass_form_fielddirective includes any additional form fields your frontend sends (like auth tokens) so they're passed to the Sails backend.
Start with the timeout and Sails config fixes first—those are the most common culprits for this 99% disconnect issue. After making changes, restart Nginx and Sails, then test the upload again.
内容的提问来源于stack exchange,提问作者anas p a

