fix(upload): restore configurable batch-size for reverse proxies (#509)

Regression of #208. PR #214 (commit 02a46e0, re-merged at 9b7495e)
shipped the configurable `general_max_upload_batch_size_mb` setting so
users behind Cloudflare Tunnel and other reverse proxies with
per-request size caps could lower the chunked-upload size below their
proxy's limit. Six days later the "Merge main into beta for
release/beta-to-main" commit (28793bb) resolved its conflict by
keeping main's older tree — which silently deleted the migration
(072), the setting input on Settings → General, the i18n strings, the
`useSettingsState` field, and the read in PhotoUpload.tsx, putting the
hardcoded 500MB chunk back. Galleries fronted by Cloudflare have
quietly been broken on batch uploads since then.

Re-applying exactly the same change set:

- `backend/migrations/core/072_add_max_upload_batch_size.js`
  recreated, with a comment pointing at the regression in case the
  same merge accident happens again.
- `frontend/src/components/admin/PhotoUpload.tsx` line 168 now reads
  the setting from query cache and falls back to 95MB (Cloudflare-safe
  headroom under 100MB).
- `useSettingsState.ts`, `GeneralTab.tsx`, `en.json`, `de.json` —
  added the field to the state type + defaults + load path + the
  Site-Configuration input.

Existing installs are safe either way:
- Ran original 072 then lost the file: migrations table still has the
  filename, so the runner skips re-applying. The setting row in
  `app_settings` is also untouched (the deletion was source-only, no
  down migration ran). Now the new code starts reading it again.
- Installed after the regression: migrations runner picks up the new
  072 normally and seeds the setting at 95.
This commit is contained in:
Paul Nothaft
2026-05-17 00:42:22 +02:00
parent 33de294d57
commit 98f3c3df41
6 changed files with 75 additions and 2 deletions
@@ -163,9 +163,14 @@ export const PhotoUpload: React.FC<PhotoUploadProps> = ({ eventId, onUploadCompl
setUploadProgress(0);
setUploadIds([]);
// For large uploads, chunk the files by both count AND size to prevent memory/network issues
// For large uploads, chunk the files by both count AND size to prevent memory/network issues.
// #509: the per-chunk byte cap MUST be tunable so users behind Cloudflare Tunnel and other
// reverse proxies with request-size limits can drop it below their proxy's cap. Falls back
// to 95MB (Cloudflare-safe headroom under 100MB) when the setting is unset — that matches
// the value the migration seeds and is what worked in #208's resolution.
const MAX_FILES_PER_CHUNK = Math.max(1, Math.min(50, maxFilesPerUpload)); // Max 50 files per chunk
const MAX_BYTES_PER_CHUNK = 500 * 1024 * 1024; // Max 500MB per chunk (nginx limit is 1GB)
const maxBatchSizeMb = Number(settings?.general_max_upload_batch_size_mb) || 95;
const MAX_BYTES_PER_CHUNK = maxBatchSizeMb * 1024 * 1024;
const chunks: File[][] = [];
let currentChunk: File[] = [];