How-to2026-08-276 min läsning

När en stor PDF-uppladdning avvisas: gränsen på 100 MiB för begärandekroppen och felet som pekar i fel riktning

En begärandekropp får vara 100 MiB, alltså 104 857 600 byte inklusive multipart-ramverket; över gränsen svarar slutpunkter för operationer med 400 och code bad_request samt en detalj om ett misslyckat multipart-fält, inte 413, och med Idempotency-Key finns en andra gräns på 100 MiB för svarsbufferten, där du får 500 och inget cachas.

PDF123 · Updated 2026-08-27

En stor PDF som inte går att ladda upp är oftast inte en trasig fil. Begärandekroppen nådde gränsen per förfrågan: 100 MiB, eller 104 857 600 byte. Den mäts över hela kroppen, multipart-gränser och fälthuvuden inräknade, och exakt den siffran passerar medan en enda byte mer avvisas.

Felet som kommer tillbaka pekar någon annanstans. Slutpunkter för operationer svarar 400 med code satt till bad_request och en detalj som säger att ett multipart-fält inte kunde läsas, utan att nämna storleken någonstans. En klient som förgrenar sig på code arkiverar det som ett parameterfel och går iväg för att kontrollera fältnamn, när det som ska ändras är filstorleken.

Samma 100 MiB styr också den motsatta riktningen. En förfrågan med Idempotency-Key läser in svaret i minnet innan det cachas, mot samma siffra, och över den får anroparen 500 medan operationen redan har körts klart. En siffra, två motsatta felmoder.

                     100 MiB = 104 857 600 byte (exakt denna siffra passerar)
                                   |
                +------------------+------------------+
                |                                     |
         inkommande (begärandekropp)        utgående (svarskropp)
   hela kroppen, multipart-gränser          bara med Idempotency-Key,
   och fälthuvuden inräknade; en            en cachemiss och ett
   operation och en pipeline delar den      upstream-2xx
   över: 400 + bad_request                  över: 500, inget cachat
   (detalj: ett multipart-fält misslyckades)

Figurnot: en gräns, och den inkommande och utgående sidan av den ger olika statuskoder med motsatta följder.

Gränsen räknar hela begärandekroppen, gränser inräknade

100 MiB begränsar kroppen för en enskild förfrågan, inte storleken på en enskild fil och inte storleken efter dekomprimering.

  • En enskild operation och en pipeline i flera steg delar siffran. Att dela upp arbetet i 10 steg inom ett enda anrop till /api/v1/pipeline gör inte taket till 1 GB; antalet steg påverkar bara körtiden.
  • Gränsvärdet självt passerar: en begärandekropp på 104 857 600 byte går igenom, 104 857 601 byte gör det inte.
  • Kroppen bär varje fälts huvuden och gränsmarkörerna utöver filbyten, så utrymmet som återstår för en enskild fil är strikt under 100 MiB. En fil på exakt 104 857 600 byte avvisas.

Den sista punkten är där praktiken lättast slinter: curl -F lägger till gränserna åt dig, så att jämföra en filstorlek mot den linjen kan aldrig stämma.

Över gränsen får du 400 och bad_request

Ett svar över gränsen använder inte 413 och innehåller ingen formulering om storlek alls. Reproducera det med en kropp en byte över:

head -c 104857601 /dev/zero > /tmp/over.bin
curl -s -X POST "$API_BASE/api/v1/misc/compress-pdf" \
  -H "X-API-KEY: $API_KEY" \
  -F "fileInput=@/tmp/over.bin"
HTTP/1.1 400 Bad Request
content-type: application/problem+json

{ "code": "bad_request",
  "detail": "failed to read multipart field: Error parsing `multipart/form-data` request",
  "hint": "Fix request parameters or upload a valid PDF.",
  "status": 400,
  "title": "Bad Request",
  "type": "https://pdf123.xyz/developers/errors#bad_request" }

Tre saker att läsa tillsammans:

  • Statusen är 400. En misslyckad läsning av kroppen klassas här som bad_request och går fortfarande genom problem+json, så en klient skriven för ”över gränsen betyder 413” tar fel gren.
  • code är bad_request, en riktig post i felkodstabellen. Den faller inte igenom till en generisk gren; den delar en kod med ett felstavat fältnamn eller en trasig multipart-kodning, och inget i den tabellen handlar om storlek.
  • hint säger åt dig att ladda upp en giltig PDF. Filen du laddade upp är med stor sannolikhet en giltig PDF som råkar vara några hundra byte för stor.

Ledtråden är alltså inte statuskoden utan antalet byte i kroppen: vid en 400 vars detail innehåller failed to read multipart field, mät storleken i stället för att gå tillbaka genom formuläret.

413 förekommer faktiskt hos oss, bara inte på slutpunkter för operationer. Varje ingång som tar emot en filuppladdning har höjts till 100 MiB, medan slutpunkter utan uppladdning fortfarande körs på HTTP-ramverkets (Rusts axum) standard på 2 MiB, där en kropp över gränsen får 413 och en rad klartext:

head -c 2097153 /dev/zero > /tmp/big.json
curl -s -w '\n%{http_code}\n' -X POST "$API_BASE/api/v1/auth/login" \
  -H 'Content-Type: application/json' \
  --data-binary @/tmp/big.json
Failed to buffer the request body: length limit exceeded
413

Ett faktum, två statuskoder och två svarskroppar beroende på slutpunkten. Att bära med sig endera erfarenheten till den andra leder dig fel.

Det andra felet med samma siffra, på vägen tillbaka

En förfrågan med Idempotency-Key cachar sitt svar så att ett återförsök kan spela upp det. Att cacha innebär att först läsa in svarskroppen i minnet, och den läsningen begränsas av samma 100 MiB, även om den kräver en mycket snävare uppsättning villkor:

  1. Förfrågan bar Idempotency-Key.
  2. Cachen missade, så denna nyckel är ny.
  3. Den uppströms operationen returnerade 2xx.

Misslyckanden cachas inte och passerar rakt igenom, så bara en lyckad stor utdata når denna gräns.

Det som händer där är poängen värd att komma ihåg: du får 500, och inget skrivs till cachen. Operationen har redan körts, ändå ser anroparen ett misslyckande; eftersom inget cachades kör återförsöket hela saken igen. Idempotensnyckeln finns för att eliminera dubbelarbete och misslyckas precis när den behövs som mest, genom att klä en färdig körning som ett serverfel. Cachen lever i processminnet och skrivs aldrig till disk, så en omstart rensar den; för semantiken se Idempotency-Key: säkra återförsök för PDF-jobb.

100 MiB är ingen konfigurerbar plattformsinställning

Siffran går inte att ändra. Ingen miljövariabel höjer eller sänker den, åt något håll; en annan siffra betyder att koden ändras och avbildningen byggs om. Söker du den som en driftsättningsinställning hittar du ingen.

Den är också mer än en kvot. Byten i en begärandekropp läses in i minnet i sin helhet före bearbetningen, så varje samtidig stor uppladdning håller en jämförbar mängd vid sidan av. Att höja taket innebär att acceptera en högre minnestopp tillsammans med det: siffran är också det som hindrar en enskild förfrågan från att dra ner processen.

En egen installation med standardinställningar har ingen omvänd proxy, och portalen kontrollerar inte storleken före inskickning, så avvisandet kommer från serverns egen gräns. Sätter du nginx framför träffar du nginx först: client_max_body_size tillåter bara 1 MiB som standard och svarar 413, en form nära den i jämförelsen ovan och lätt att missta för samma gräns.

Vad du gör när du träffar den

Billigast först:

  1. Mät innan du skickar. Jämför begärandekroppens byteantal med 104 857 600 innan förfrågan går ut, och lämna utrymme för gränserna. Det slår att läsa en statuskod i efterhand.
  2. Komprimera filen under gränsen. En skannings storlek kommer mest från bildlagret, och omkomprimering tar rutinmässigt bort en synlig del av den. Komprimera en PDF körs i webbläsaren, utan skript.
  3. Dela upp arbetet över flera anrop. När innehållet går att dela, dela det och skicka det i några förfrågningar: mindre besvär än att höja taket, och det höjer inte minnesmängden som en förfrågan håller.
  4. Ändra bara gränsen vid ett hårt krav på en enda förfrågan. Det betyder att ändra kod och bygga om, och att acceptera minneskostnaden från föregående avsnitt.

Den här gränsen kräver att klienten bestämmer i förväg

Båda felen pekar mot en slutsats: 100 MiB måste räknas ut av klienten innan den skickar. Inkommande svaras du med bad_request, en kod som inte säger något om storlek; utgående med 500, vilket ser ut som ett serverfel. Att räkna byten innan förfrågan lämnar är det enda sättet att bedöma som inte beror på vad ett felmeddelande säger.

Open tool
Process in the browser — no watermark, files removed after the job.
Open tool