Chunked Transfer i webbutveckling — vad är det, format och principen för chunk-överföring

Författare: IT Sectr Publicerad: 2026-03-10 Lästid: 9 min

Chunked Transfer — är en mekanism i HTTP-protokollet där servern överför svarstexten i separata fragment (chunks), utan att i förväg ange den totala datastorleken. Varje chunk innehåller sin egen storlek i hexadecimalt format och data av angiven längd, och avslutas med en slutgiltig chunk av noll storlek. Enligt MDN Web Docs, 2025, aktiveras Transfer-Encoding: chunked automatiskt av servern när svarsstorleken inte är känd i förväg — till exempel vid generering av innehåll i farten eller strömmande överföring av data.

Huvudpunkter

  • Chunked Transfer — överföring av HTTP-svar i delar utan föregående angivande av Content-Length.
  • Transfer-Encoding: chunked — headern som aktiverar chunk-läget för dataöverföring.
  • Varje chunk innehåller storlek i hex, data och avslutande CRLF, och slutet markeras av en chunk med noll storlek.
  • Streaming — den huvudsakliga tillämpningen av chunked transfer för överföring av ljud, video och SSE-händelser.
  • Chunked Transfer är inkompatibelt med Content-Length headern — de används inte samtidigt.

Vad är Chunked Transfer?

Chunked Transfer är en HTTP-mekanism definierad i HTTP/1.1-specifikationen (RFC 7230, avsnitt 4.1) som gör det möjligt för servern att skicka svarstexten i delar utan att ange den totala Content-Length. Istället för att beräkna svarsstorleken före sändning, börjar servern omedelbart överföringen och skickar data i fragment allt eftersom de blir klara. Varje fragment åtföljs av sin egen storleksheader, vilket gör att klienten kan sammanställa svaret från bitar.

Mekanismen aktiveras av headern Transfer-Encoding: chunked. När klienten ser denna header i svaret, vet den att texten kommer att överföras i chunks och måste läsa svaret i en loop: läs chunk-storleken, läs sedan data av angiven storlek och upprepa sedan. Processen avslutas när en chunk med noll storlek påträffas. Chunked Transfer är en obligatorisk del av HTTP/1.1, som stöds av alla moderna webbservrar och HTTP-klienter.

Huvudskälet till att använda chunked transfer är dynamisk innehållsgenerering. När servern genererar ett svar baserat på en databasfråga, externt API eller långvarig beräkning, kan den inte i förväg veta resultatets storlek. Istället för att buffra hela svaret i minnet (vilket är riskabelt för stora volymer), aktiverar servern Transfer-Encoding: chunked och skickar data när den är klar. Detta är särskilt viktigt för servrar med begränsat minne och för svar vars storlek kan vara mycket stor — från 100 MB och uppåt.

Skillnad mellan HTTP/1.1 chunked och HTTP/2

I HTTP/2 finns chunked transfer-mekanismen som sådan inte, eftersom protokollet använder multiplexering av strömmar på ramnivå. I HTTP/2 överförs data av valfri storlek i DATA-ramar, och storleken på svarstexten behöver inte deklareras i förväg — strömmen kan stängas när som helst. Moderna servrar konverterar automatiskt HTTP/1.1 chunked-svar till motsvarande strömmande överföring vid proxning till HTTP/2 upstream. Chunked Transfer förblir relevant för HTTP/1.1-anslutningar.

Hur fungerar chunk-överföring

När servern bestämmer sig för att använda Chunked Transfer, beräknar den inte Content-Length, utan skickar headern Transfer-Encoding: chunked. Sedan bildas svarstexten som en sekvens av chunks. Varje chunk börjar med en rad som innehåller chunk-storleken i hexadecimalt format (utan prefixet 0x), följt av CRLF ( ). Därefter kommer chunk-data av angiven storlek, avslutad med CRLF. Den sista chunken har storlek 0, efter vilken trailer-headers kan följa.

Den hexadecimala storleken gör det möjligt att överföra chunks av valfri storlek — från 1 byte till teoretiskt obegränsad volym. I praktiken väljs chunk-storleken av servern: typiska värden är 4 KB, 8 KB eller 16 KB. Optimal chunk-storlek är en multipel av TCP-segmentets storlek (vanligtvis 1460 byte för Ethernet) för att minimera fragmentering på transportnivån. Nginx använder som standard chunks på 4 KB, Apache — på 8 KB.

Klienten som har fått Transfer-Encoding: chunked är skyldig att läsa svaret chunk för chunk fram till den sista noll-chunken. Om klienten inte stöder chunked transfer kan servern inte använda detta läge. I praktiken stöder alla moderna HTTP-klienter — webbläsare, OkHttp, URLSession, curl — chunked-svar fullt ut. Strömmande läsning gör att klienten kan börja bearbeta data innan hela svaret har mottagits, vilket är avgörande för prestanda.

Chunk-elementFormatExempel
Chunk-storlekHEX + CRLF1000
Chunk-data[storlek byte] + CRLF[4096 byte data]
Avslutande chunk0 0
Trailer (valfritt)Headers + CRLFExpires: Wed, 21 Oct 2025

Trailer-headers i Chunked Transfer

Chunked Transfer stöder trailer-headers — ytterligare HTTP-headers som överförs efter den sista chunken. Detta är användbart för metadata som blir känd först efter att svarsgenereringen är klar: till exempel Content-MD5 eller X-Compression-Ratio. Trailer-headers måste deklareras i Trailer-headern: Content-MD5, X-Compression-Ratio. I praktiken används trailers sällan — de flesta servrar inkluderar dem inte i svar.

Format för chunked svar

Ett chunked svar har en strikt definierad struktur som klienten måste tolka korrekt. Låt oss undersöka ett fullständigt exempel på ett HTTP-svar med Transfer-Encoding: chunked. Efter headers och den tomma raden börjar svarstexten. Textens struktur är en sekvens: chunk_storlek data chunk_storlek data ... till 0 . Varje storlek överförs i hexadecimalt talsystem med ASCII-tecken.

Exempel på serversvar med Chunked Transfer:
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

7
Hello
6
World!
0

I detta exempel överför servern strängen „Hello World!” i två chunks. Den första chunken på 7 byte innehåller „Hello ”, den andra — 6 byte „World!”. Klienten samlar data från båda chunks och får den fullständiga strängen. Viktigt: chunk-storleken omfattar endast data, inte CRLF-avskiljarna för själva chunksen. Den sista tomma chunken (0 ) meddelar klienten att överföringen är slut.

kotlin
import java.net.HttpURLConnection
import java.io.BufferedReader
import java.io.InputStreamReader

fun readChunkedResponse() {
    val url = java.net.URL("https://stream.example.com/data")
    val connection = url.openConnection() as HttpURLConnection
    val reader = BufferedReader(
        InputStreamReader(connection.inputStream)
    )

    var line: String?
    while (reader.readLine().also { line = it } != null) {
        println("Chunk: $line")
    }
    reader.close()
}

Tolkning av chunked svar i OkHttp

OkHttp abstraherar programmeraren helt från detaljerna i Chunked Transfer. Vid mottagning av ett svar med Transfer-Encoding: chunked samlar OkHttp automatiskt ihop chunksen och tillhandahåller programmeraren den fullständiga svarstexten via response.body?.string(). För strömmande bearbetning används response.body?.source(), som returnerar en BufferedSource och gör det möjligt att läsa data när den kommer. Programmeraren behöver inte manuellt tolka hex-storlekar och CRLF — biblioteket gör det automatiskt.

Chunked Transfer vs Content-Length

Content-Length och Transfer-Encoding: chunked är två ömsesidigt uteslutande sätt att ange storleken på HTTP-meddelandets brödtext. Content-Length är en header som innehåller den exakta storleken på texten i byte. Den är obligatorisk för svar vars storlek är känd i förväg och för förfrågningar med text (POST, PUT). Content-Length gör det möjligt för klienten att i förväg allokera en buffert av lämplig storlek och kontrollera att alla data har mottagits.

Chunked Transfer används när textens storlek inte är känd i förväg. Detta inträffar i tre huvudsakliga scenarier: dynamisk innehållsgenerering (till exempel en databasfråga vars resultat ännu inte har mottagits), strömmande överföring av stora filer (för att inte buffra hela filen i minnet) och Server-Sent Events (SSE) för överföring av realtidshändelser. Valet mellan Content-Length och chunked är serverns ansvar. Om servern känner till storleken innan överföringen börjar, bör den använda Content-Length som en enklare och mer förutsägbar mekanism.

HTTP/1.1-specifikationen förbjuder samtidig användning av Content-Length och Transfer-Encoding: chunked. Om servern skickar båda headers måste klienten ignorera Content-Length och behandla svaret som chunked. Prioriteten för Transfer-Encoding över Content-Length fastställdes i RFC 7230 för fall där en proxyserver ändrar svarstexten och inte kan behålla den ursprungliga Content-Length. Vissa äldre HTTP-klienter hanterar denna situation felaktigt, men moderna implementeringar följer specifikationen.

När Content-Length är omöjlig

Det finns scenarier där Content-Length i princip inte kan beräknas i förväg. Dynamiska rapporter som genereras på användarens begäran med filtrering och aggregering — servern känner inte till datavolymen förrän databasfrågan är klar. Strömmande video som överförs från en kamera i realtid — storleken är oändlig. SSE och long polling för notifieringar — svaret kan pågå under obegränsad tid. I alla dessa fall är Chunked Transfer den enda korrekta mekanismen.

Streaming baserat på chunked transfer

Chunked Transfer ligger till grund för många streaming-teknologier på webben. Den mest kända är Server-Sent Events (SSE), där servern skickar händelser till klienten över en enda HTTP-anslutning med Transfer-Encoding: chunked. SSE använder ett speciellt textformat (data: meddelande ), men transportlagret är vanlig chunked transfer. Webbläsaren tar emot händelser när de skickas av servern, utan att vänta på att svaret ska slutföras.

Strömmande ljud och video bygger också på Chunked Transfer. Mediaservrar som Nginx RTMP och Wowza Streaming Engine skickar mediadata i chunks via HTTP. Spelaren på klientsidan börjar spela upp när den första chunken har tagits emot, utan att vänta på att filen ska laddas helt. Detta minskar tiden till dess att uppspelningen startar (Time to First Frame) från tiotals sekunder till 1-2 sekunder. YouTube och Netflix använder just denna metod för sina HTTP-strömmar.

Vid utveckling av mobilapplikationer används Chunked Transfer för att överföra stora datavolymer utan att ladda hela svaret i minnet. Vid inläsning av bilder via Coil eller Glide på Android läser biblioteken strömmande data i chunks och avkodar bilden gradvis. Detta gör det möjligt att visa stora bilder (10+ MB) utan OutOfMemoryError. OkHttp stöder strömmande läsning via response.body?.byteStream(), som returnerar en InputStream som läser data chunk för chunk.

Chunked transfer i gRPC och GraphQL

gRPC använder HTTP/2, där strömmande överföring är inbyggd på protokollnivå och inte kräver en separat chunked-mekanism. GraphQL-servrar som arbetar via HTTP/1.1 kan använda Chunked Transfer för strömmande överföring av prenumerationsresultat (subscriptions). Apollo Server och Hasura skickar chunked-svar för GraphQL-prenumerationer och överför händelser när de inträffar. Klienten får realtidsuppdateringar utan att behöva polling.

Fördelar och begränsningar

Chunked Transfer ger viktiga fördelar för webbapplikationer. Omedelbar dataöverföring — servern buffrar inte svaret före sändning, vilket minskar fördröjningen (latensen) till den första byten. Strömmande bearbetning — klienten kan börja bearbeta data när den kommer, utan att vänta på fullständig inläsning. Inga minnesbegränsningar — servern lagrar inte hela svaret i minnet, vilket är avgörande för stora datamängder. Möjlighet att överföra oändliga strömmar — SSE, livevideo, övervakning.

Chunked Transfer har dock begränsningar. Overhead för varje chunk är 6-12 byte för storlek + CRLF, vilket för ett stort antal små chunks (till exempel 100 byte) kan öka svarsstorleken med 10-15%. Omöjlighet att ange exakt storlek — klienten kan inte i förväg allokera en buffert eller visa en förloppsindikator. Problem med proxyservrar — vissa äldre proxyservrar stöder inte chunked transfer och kan inte cachelagra sådana svar. Brist på stöd för att återuppta nedladdningar — för delvis mottagna chunked-svar kan ingen Range-förfrågan göras.

Enligt HTTP Archive, 2025 använder cirka 35% av alla HTTP-svar Transfer-Encoding: chunked. Bland dessa dominerar dynamiska sidor (60%), API-svar (25%) och mediaströmmar (15%). Statiska filer använder nästan alltid Content-Length eftersom deras storlek är känd i förväg. Andelen chunked-svar minskar gradvis i takt med att HTTP/2 sprids, där strömmande överföring implementeras på ramnivå utan behov av en extra Transfer-Encoding-header.

Praktiska rekommendationer

Vid mobilapplikationsutveckling, använd Chunked Transfer för att ladda stora filer (bilder, video) och för API-förfrågningar som returnerar stora dataarrayer. OkHttp stöder chunked transfer fullt ut utan ytterligare konfiguration. För uppladdning till servern (upload) tillämpas inte Chunked Transfer — Transfer-Encoding används inte för upload i HTTP/1.1. På iOS stöder URLSession både sändning och mottagning av chunked-data utan särskild konfiguration. Strömmande JSON-tolkning (till exempel via Jackson Streaming API eller Moshi) gör det möjligt att bearbeta stora JSON-arrayer när chunked-strömmen kommer.

Vanliga frågor

Hur aktiverar servern Chunked Transfer?

Servern aktiverar Chunked Transfer automatiskt när svarsstorleken är okänd. Nginx lägger till Transfer-Encoding: chunked om Content-Length inte är inställd. I Spring Boot använder StreamingResponseBody och SseEmitter automatiskt chunked transfer. I Node.js Express blir svaret chunked om res.write() och res.end() anropas utan Content-Length.

Kan Content-Length och chunked användas samtidigt?

Nej, HTTP/1.1-specifikationen förbjuder samtidig användning av Content-Length och Transfer-Encoding: chunked. Om servern skickar båda headers måste klienten ignorera Content-Length och behandla svaret som chunked. Denna regel fastställdes i RFC 7230 för kompatibilitet med proxyservrar som kan ändra svarstexten.

Vilken chunk-storlek är optimal?

Den optimala chunk-storleken beror på scenariot. För vanliga webbsidor — 4-8 KB. För videostreaming — 16-64 KB. För SSE — minimala chunks på 1-2 KB för att minska fördröjningen. Chunk-storleken bör vara en multipel av TCP-segmentets storlek (1460 byte för Ethernet) för att minimera fragmentering på transportnivån.

Fungerar Chunked Transfer via proxy?

Moderna proxyservrar (Nginx, HAProxy, Envoy) stöder Chunked Transfer. Proxyn kan vidarebefordra chunks utan buffring (streaming) eller buffra hela svaret och skicka det igen med Content-Length. Äldre proxyservrar kan buffra chunked-svaret tills det är klart, vilket ökar fördröjningen. HTTP/2 löser detta problem på protokollnivå.

Vad är skillnaden mellan Chunked Transfer och HTTP chunked encoding?

Det är samma sak. Chunked Transfer är det fullständiga namnet på mekanismen från HTTP/1.1-specifikationen. HTTP chunked encoding är samma sak, ibland använt i biblioteksdokumentation. Transfer-Encoding: chunked är headern som aktiverar detta läge. Alla tre termerna beskriver samma mekanism för att överföra data i delar.

Sammanfattning

  • Chunked Transfer — HTTP/1.1-mekanism som överför svarstexten i chunks utan att i förväg ange Content-Length.
  • Transfer-Encoding: chunked — headern som aktiverar chunk-överföring; varje chunk innehåller hex-storlek, data och CRLF.
  • Avslutande chunk med noll storlek signalerar slutet på överföringen, efter vilken trailer-headers kan följa.
  • Dynamic content streaming — huvudsaklig tillämpning: dynamiska sidor, SSE, strömmande ljud/video, långa rapporter.
  • Content-Length och chunked är ömsesidigt uteslutande — specifikationen förbjuder samtidig användning av dessa headers.
  • Fördelar — minskad fördröjning, minnesbesparing, möjlighet att överföra oändliga strömmar och strömmande bearbetning på klientsidan.
  • Begränsningar — overhead för chunk-headers, omöjlighet att visa förlopp, problem med äldre proxyservrar.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också