From 3d2c7c25c288db2ee21e3350a1664b82d6115bb1 Mon Sep 17 00:00:00 2001 From: NovaCPX Admin Date: Wed, 15 Jul 2026 14:49:53 -0500 Subject: [PATCH] fix: File Manager large uploads had no server-processing feedback and short nginx timeouts Reaching 100% in the upload progress bar only means the browser finished SENDING the bytes to nginx - it does not mean the server has finished receiving/saving the file. For multi-GB files this gap was invisible, making a genuinely-still-working upload look frozen at 100 percent, leading to a premature reload (confirmed via nginx access log: status 499, client closed request). nginx-panel.conf: added fastcgi_request_buffering off on the admin panels /api/ location so nginx streams the body straight to PHP-FPM instead of fully buffering it to a temp file first and reading it back (a full extra disk I/O pass for large files); also added client_body_timeout/fastcgi_send_timeout/send_timeout at 1800s alongside the existing fastcgi_read_timeout, since those are separate timeout phases that previously still defaulted to 60s. admin.js: added an xhr.upload load-complete handler that switches the dialog to a clear "Finishing up on the server..." state once the send phase hits 100%, so large uploads no longer look stuck during the save phase. --- deploy/nginx-panel.conf | 7 +++++++ panel/assets/js/admin.js | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/deploy/nginx-panel.conf b/deploy/nginx-panel.conf index 8a15a42..5a931b1 100644 --- a/deploy/nginx-panel.conf +++ b/deploy/nginx-panel.conf @@ -47,6 +47,13 @@ http { fastcgi_param SCRIPT_FILENAME /srv/novacpx/public/api/index.php; fastcgi_param SERVER_PORT 8882; fastcgi_read_timeout 1800; + fastcgi_send_timeout 1800; + client_body_timeout 1800; + send_timeout 1800; + # Stream the request body straight to PHP-FPM instead of nginx buffering + # the whole thing to a temp file first and then reading it back — cuts a + # full extra disk read+write pass for large uploads (ISOs, installers). + fastcgi_request_buffering off; fastcgi_param PHP_VALUE "upload_max_filesize=20G post_max_size=20G max_execution_time=1800 diff --git a/panel/assets/js/admin.js b/panel/assets/js/admin.js index f6531d3..0c3d77f 100644 --- a/panel/assets/js/admin.js +++ b/panel/assets/js/admin.js @@ -4861,6 +4861,18 @@ window.fmSubmitUpload = () => { if (pctEl) pctEl.textContent = pct + '%'; if (bytesEl) bytesEl.textContent = fmFormatBytes(e.loaded) + ' / ' + fmFormatBytes(e.total); }); + // Reaching 100% here only means the browser finished SENDING the bytes — the + // server (nginx + PHP) still has to receive/move the file, which for large + // files can take a genuine extra stretch with no further upload events. Make + // that explicit so it doesn't look frozen. + xhr.upload.addEventListener('load', () => { + const pctEl = document.getElementById('fm-upload-pct'); + const bytesEl = document.getElementById('fm-upload-bytes'); + const bar = document.getElementById('fm-upload-bar'); + if (bar) bar.style.background = '#f59e0b'; + if (pctEl) pctEl.textContent = 'Finishing up…'; + if (bytesEl) bytesEl.textContent = 'Upload sent — waiting for the server to finish saving the file. Large files can take a few extra minutes here. Do not close or reload this page.'; + }); xhr.onload = () => { let res = null;