fix(upload): use correct experimental.proxyClientMaxBodySize key + client-side size guard
The previous attempt put 'middlewareClientMaxBodySize' at the top level of NextConfig — Next 16.1 rejected it as an unrecognised key. Inspecting the shipped config schema (node_modules/next/dist/server/config-schema.js) revealed the option lives under experimental and was renamed to 'proxyClientMaxBodySize' when middleware.ts → proxy.ts; the old name is still accepted but deprecated. Switched to the new name and confirmed Next now lists it in the Experiments banner at boot. While we were at it the cap was bumped to 500MB (was 100MB) so batch uploads have headroom over the 30MB-per-file bucket limit. Added a client-side pre-flight in JobFilesPanel: rejects individual files >30MB and total batches >400MB *before* hitting the server, with inline error messaging instead of a cryptic 'Unexpected end of form' bounce. Also raised serverActions.bodySizeLimit to 500mb to match.
This commit is contained in:
@@ -63,6 +63,9 @@ export function JobFilesPanel({
|
||||
);
|
||||
}
|
||||
|
||||
const MAX_FILE_BYTES = 30 * 1024 * 1024;
|
||||
const MAX_BATCH_BYTES = 400 * 1024 * 1024; // leaves headroom under the 500MB proxy cap
|
||||
|
||||
function UploadForm({ jobId }: { jobId: string }) {
|
||||
const [state, action, pending] = useActionState(
|
||||
uploadJobFilesAction,
|
||||
@@ -82,6 +85,11 @@ function UploadForm({ jobId }: { jobId: string }) {
|
||||
}
|
||||
}, [state]);
|
||||
|
||||
const totalBytes = selected.reduce((s, f) => s + f.size, 0);
|
||||
const overSize = selected.find((f) => f.size > MAX_FILE_BYTES);
|
||||
const overBatch = totalBytes > MAX_BATCH_BYTES;
|
||||
const blocked = Boolean(overSize) || overBatch;
|
||||
|
||||
return (
|
||||
<form
|
||||
ref={formRef}
|
||||
@@ -111,11 +119,25 @@ function UploadForm({ jobId }: { jobId: string }) {
|
||||
Dosya seç
|
||||
</Button>
|
||||
<span className="text-muted-foreground text-xs flex-1">
|
||||
{selected.length > 0
|
||||
? `${selected.length} dosya seçildi (${formatSize(selected.reduce((s, f) => s + f.size, 0))})`
|
||||
: "Tarama (STL/OBJ), görsel veya PDF — max 30MB / dosya"}
|
||||
{selected.length > 0 ? (
|
||||
overSize ? (
|
||||
<span className="text-destructive">
|
||||
{overSize.name} 30MB'tan büyük (her dosya maksimum 30MB).
|
||||
</span>
|
||||
) : overBatch ? (
|
||||
<span className="text-destructive">
|
||||
Toplam {formatSize(totalBytes)} — 400MB sınırını aşıyor. Daha az dosya seçin.
|
||||
</span>
|
||||
) : (
|
||||
<>
|
||||
{selected.length} dosya seçildi ({formatSize(totalBytes)})
|
||||
</>
|
||||
)
|
||||
) : (
|
||||
"Tarama (STL/OBJ), görsel veya PDF — max 30MB / dosya"
|
||||
)}
|
||||
</span>
|
||||
<Button type="submit" size="sm" disabled={pending || selected.length === 0}>
|
||||
<Button type="submit" size="sm" disabled={pending || selected.length === 0 || blocked}>
|
||||
{pending ? (
|
||||
<>
|
||||
<Loader2 className="size-4 animate-spin" />
|
||||
|
||||
Reference in New Issue
Block a user