Multipart Upload ve webovém vývoji: podstata, struktura a jak funguje multipart/form-data

Autor: IT Sectr Publikováno: 2026-03-10 Doba čtení: 9 min

Multipart Upload je HTTP mechanismus, který umožňuje přenášet několik heterogenních částí dat v jediném požadavku, včetně textových polí a binárních souborů. Každá část je oddělena jedinečným hraničním řetězcem a má vlastní hlavičku Content-Type. Podle MDN Web Docs, 2025 je multipart/form-data standardním formátem pro nahrávání souborů přes HTML formuláře a je široce používán ve webových a mobilních aplikacích pro odesílání obrázků, dokumentů a dalších souborů na server.

Hlavní body

  • Multipart Upload — přenos několika částí dat v jednom HTTP požadavku s oddělením pomocí boundary.
  • multipart/form-data — standardní typ MIME pro nahrávání souborů z HTML formulářů a mobilních aplikací.
  • Boundary — jedinečný řetězec oddělující části složeného požadavku, automaticky generovaný HTTP klienty.
  • Každá část obsahuje hlavičky Content-Disposition a Content-Type popisující název pole a typ souboru.
  • Multipart Upload je efektivnější než vícenásobné požadavky — jeden POST nahrazuje N samostatných volání serveru.

Co je Multipart Upload?

Multipart Upload je metoda přenosu dat pomocí protokolu HTTP, při které se tělo požadavku skládá z několika logicky oddělených částí. Každá část může obsahovat data různého typu: textové pole formuláře, binární soubor, JSON objekt nebo obrázek. Všechny části jsou zabaleny do jednoho POST požadavku, což nahrazuje potřebu odesílat N samostatných HTTP volání. Multipart Upload je nedílnou součástí webových formulářů a API pro nahrávání souborů.

Formát multipart byl definován ve specifikaci RFC 2046 jako součást standardu MIME pro e-mailové zprávy a poté adaptován pro HTTP v RFC 1867. Dnes se ve webovém vývoji používá téměř výhradně multipart/form-data — jeden z podtypů multipart, určený pro formuláře obsahující soubory. Další podtypy — multipart/mixed (pro libovolné přílohy) a multipart/byteranges (pro částečné stahování souborů) — se používají mnohem méně často.

Zásadní rozdíl mezi multipart a jednoduchým application/x-www-form-urlencoded spočívá v tom, že druhý jmenovaný kóduje všechna data do řetězce kompatibilního s URI a nepodporuje binární soubory. Multipart/form-data naopak přenáší každý soubor v jeho původní binární podobě bez kódování, což je efektivnější a neztrácí přesnost. Velikost požadavku u multipart je pouze o 5-15% větší než součet velikostí souborů kvůli režii na hlavičky částí a hranice.

Kdy se Multipart Upload používá

Multipart Upload se používá všude tam, kde je vyžadováno nahrávání souborů: avatary a profilové fotografie na sociálních sítích, přílohy v messengerech, dokumenty v CRM systémech, obrázky produktů v internetových obchodech. V mobilních aplikacích se Multipart Upload používá pro odesílání mediálních souborů na server — fotografie z fotoaparátu zařízení, hlasové záznamy, video fragmenty. Podle údajů Cloudflare Research přibližně 15% všech POST požadavků na webu používá multipart/form-data.

Rozdíl mezi multipart a chunked transfer

Multipart Upload a Chunked Transfer jsou různé mechanismy. Multipart rozděluje požadavek na obsahové části (pole a soubory), zatímco Chunked Transfer rozděluje datový tok na fragmenty pro přenos bez znalosti celkové velikosti. Multipart může být přenášen uvnitř Chunked Transfer: server odesílá multipart odpověď po částech, aniž by znal její celkový objem. Tyto mechanismy si neodporují a řeší různé úkoly na různých úrovních.

Jak funguje multipart/form-data

Když prohlížeč odesílá formulář s atributem enctype="multipart/form-data", konstruuje tělo požadavku ve formátu multipart. Každé pole formuláře se stává samostatným blokem, odděleným od ostatních hraničním řetězcem (boundary). Hranice je generována automaticky a představuje jedinečnou sekvenci znaků, která se zaručeně nevyskytuje uvnitř dat. Klient přidává tuto hranici do hlavičky Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryX7K.

Každý blok začíná --boundary a obsahuje hlavičky Content-Disposition s názvem pole (name) a pro soubory původním názvem souboru (filename). Za prázdným řádkem následují přímo data pole nebo obsah souboru v binární podobě. Požadavek končí řetězcem --boundary--. Server analyzuje přijatý tok: nejprve najde hranici, poté extrahuje hlavičky každé části, určí typ dat a předá je handleru formuláře nebo API kontroléru.

Podle IETF RFC 7578 multipart/form-data nevyžaduje uvedení charset pro každou část, protože textová pole jsou považována za UTF-8 a binární části obsahují soubory v původním kódování. Velikost jedné části není protokolem omezena — omezení se konfigurují na úrovni serveru: například v Nginx přes client_max_body_size, v Spring Boot přes spring.servlet.multipart.max-file-size.

Formát boundary a jeho generování

Boundary je jedinečný řetězec, který se nesmí vyskytovat v přenášených datech. Obvykle začíná prefixem (např. ----WebKitFormBoundary nebo ----Boundary) a obsahuje náhodné znaky. Prohlížeče a HTTP klienti generují boundary automaticky. Délka boundary by podle RFC 2046 neměla přesáhnout 70 znaků. Každá část je oddělena řetězcem --boundary\r\n a konec požadavku řetězcem --boundary--\r\n.

Struktura multipart požadavku

Multipart požadavek má přísnou strukturu definovanou standardy MIME a HTTP. Hlavička požadavku nastavuje Content-Type: multipart/form-data s parametrem boundary. Tělo požadavku se skládá z posloupnosti částí, z nichž každá obsahuje vlastní hlavičky a tělo. Hlavičky části zahrnují Content-Disposition (povinný) a Content-Type (volitelný — pro soubory). Povinná je přítomnost prázdného řádku mezi hlavičkami části a jejími daty.

PrvekPříkladPovinnost
Content-Typemultipart/form-data; boundary=---Bnd123Ano
Oddělovač části---Bnd123Ano (před každou částí)
Content-Dispositionform-data; name="avatar"; filename="photo.jpg"Ano
Content-Type částiimage/jpegPro soubory
Tělo části[binární data obrázku]Ano
Závěrečná hranice---Bnd123--Ano (konec požadavku)

Příklad multipart požadavku

Podívejme se na reálný příklad multipart požadavku odesílajícího textové pole a soubor obrázku. Klient vytvoří hlavičku Content-Type s jedinečným boundary. Tělo požadavku postupně obsahuje všechna pole formuláře. Server při příjmu analyzuje tyto části a poskytuje vývojáři přístup ke každému poli jako samostatnému objektu. Tento přístup umožňuje zpracovávat složité formuláře se soubory v jednom HTTP volání.

kotlin
import okhttp3.*
import java.io.File

fun uploadFile() {
    val client = OkHttpClient()
    val imageFile = File("/path/to/photo.jpg")

    val requestBody = MultipartBody.Builder()
        .setType(MediaType.parse("multipart/form-data"))
        .addFormDataPart("username", "john_doe")
        .addFormDataPart(
            "avatar", "photo.jpg",
            RequestBody.create(
                MediaType.parse("image/jpeg"), imageFile
            )
        )
        .build()

    val request = Request.Builder()
        .url("https://api.example.com/upload")
        .post(requestBody)
        .build()

    client.newCall(request).execute().use { response ->
        println("Nahráno: ${response.isSuccessful}")
    }
}

Analýza multipart odpovědi na serveru

Na straně serveru je multipart požadavek analyzován frameworkem nebo ručně. V Spring Boot stačí anotace @RequestParam("avatar") MultipartFile file a framework automaticky extrahuje soubor z multipart požadavku. V Ktor na Kotlin se používá receiveMultipart(), v Express.js — middleware multer. Server získává přístup ke každému poli formuláře a každému nahranému souboru nezávisle, ukládá soubor na disk nebo do cloudového úložiště a vrací klientovi URL nebo identifikátor.

Výhody vícesložkového nahrávání

Multipart Upload poskytuje několik klíčových výhod oproti alternativním způsobům přenosu dat. Jeden požadavek místo mnoha — všechna pole formuláře a soubory jsou přenášeny v jednom HTTP volání, což snižuje zatížení sítě a serveru. Není třeba otevírat N spojení pro nahrání N souborů — vše je zabaleno do jednoho POST. To je důležité zejména pro mobilní aplikace, kde každé HTTP spojení znamená zpoždění a spotřebu baterie.

Binární přenos bez kódování — na rozdíl od application/x-www-form-urlencoded, kde jsou binární data kódována do base64 (zvýšení velikosti o 33%), multipart/form-data přenáší soubory v původní binární podobě. To je efektivnější z hlediska velikosti a rychlosti. U velkých souborů od 10 MB výše se rozdíl stává kritickým: multipart požadavek bude o 30% menší než URL-encoded požadavek se stejným souborem.

Libovolná struktura — multipart umožňuje kombinovat pole různých typů v libovolném pořadí. Formulář může současně obsahovat textová pole, několik souborů, JSON data a skrytá pole. Každá část má vlastní Content-Type, což umožňuje míchat textová a binární data. Pro srovnání: kódování base64 přidává 33% k velikosti, zatímco multipart pouze asi 5-15% na servisní hlavičky.

Srovnání multipart s jinými přenosovými formáty

Podle studie HTTP Archive, 2025 se multipart/form-data používá v 94% případů nahrávání souborů na webu. Alternativy — base64 v JSON (4%) a přímý přenos přes WebSocket (2%). JSON s base64 je vhodný pro API, kde jsou všechna ostatní data také v JSON, ale neefektivní pro velké soubory. WebSocket je vhodný pro real-time, ale není podporován všemi HTTP infrastrukturami. Multipart zůstává standardem pro nahrávání souborů díky své jednoduchosti a efektivitě.

Multipart Upload v mobilním vývoji

V mobilních aplikacích se Multipart Upload používá pro odesílání mediálního obsahu z uživatelských zařízení: fotografie z galerie, snímky z fotoaparátu, hlasové záznamy, soubory dokumentů. Na Androidu je standardním způsobem OkHttp s MultipartBody.Builder, který umožňuje snadné vytváření multipart požadavků. Retrofit také podporuje multipart přes anotace @Multipart a @Part. Vývojář určuje typ dat pro každou část, HTTP klient automaticky generuje správné hlavičky.

Na iOS jsou stejné úkoly řešeny přes URLSession s vlastním HTTPBodyStream nebo přes Alamofire s multipartFormData. Alamofire poskytuje pohodlnou metodu upload(multipartFormData:) pro odesílání multipart požadavků. Na obou platformách je důležité zohlednit velikost nahrávaných souborů — u velkých souborů (nad 10-20 MB) se doporučuje použít nahrávání na pozadí, aby se aplikace při minimalizaci neukončila. Na Androidu se k tomu používá DownloadManager nebo WorkManager, na iOS — URLSession s background konfigurací.

Při nahrávání souborů v mobilních aplikacích je třeba zohlednit stav sítě. Connectivity Manager na Androidu pomáhá určit, zda je dostupné Wi-Fi nebo mobilní data, a vybrat optimální okamžik pro nahrání. U velkých souborů, jako jsou videa, se doporučuje odložit nahrávání do připojení k Wi-Fi, aby se nevyužívala mobilní data uživatele. WorkManager na Androidu umožňuje konfigurovat taková omezení přes NetworkType.UNMETERED.

Optimalizace nahrávání: komprese a změna velikosti

Před odesláním souboru přes Multipart Upload mobilní aplikace často komprimují a mění velikost obrázku. Komprese JPEG s kvalitou 85% snižuje velikost souboru 3-5krát bez znatelné ztráty kvality pro zobrazení na obrazovce. Změna velikosti obrázku na 1920px na delší straně dále snižuje velikost. Na Androidu se k tomu používá Bitmap.compress(), na iOS — UIImageJPEGRepresentation s parametrem komprese 0.85. Taková optimalizace urychluje nahrávání a šetří mobilní data.

Chyby a omezení Multipart Upload

Nejčastější chybou při Multipart Upload je překročení limitu velikosti požadavku na serveru. Ve výchozím nastavení Nginx omezuje velikost těla požadavku na 1 MB (client_max_body_size) a Tomcat na 2 MB (maxSwallowSize). Pokud vývojář tyto limity nezvýší, server vrátí chybu 413 Request Entity Too Large. Řešením je explicitně nakonfigurovat maximální velikost nahrávání na serveru a zobrazit upozornění na klientovi, pokud soubor překračuje povolenou velikost.

Druhý problém — nesprávné zpracování multipart požadavků při streamování těla. Některé servery se pokoušejí načíst celý multipart požadavek do paměti před analýzou, což vede k OutOfMemoryError u velkých souborů. Moderní servery (Nginx, Spring Boot, Ktor) podporují streamovací analýzu multipart, kdy je každá část zpracovávána postupně. Vývojář by se měl ujistit, že je server nakonfigurován pro streamovací zpracování multipart požadavků.

Třetí kategorie problémů — timeouty při nahrávání velkých souborů. HTTP klienti mají nastavení readTimeout a connectTimeout, která se mohou aktivovat při dlouhodobém nahrávání souboru většího než 50-100 MB. Řešením je zvýšit timeouty pro koncové body nahrávání nebo použít chunked transfer encoding uvnitř multipart. Na mobilních zařízeních je také důležité zpracovat přerušení nahrávání a implementovat obnovení (resume) při ztrátě spojení.

Bezpečnost Multipart Upload

Nahrávání souborů přes multipart je jedním z nejzranitelnějších koncových bodů webové aplikace. Útočník může nahrát spustitelný skript přejmenováním na image.jpg. Server musí kontrolovat MIME typ nahraného souboru nikoli podle přípony, ale podle obsahu (magic bytes), omezovat povolené typy a skenovat soubory antivirem. Doporučuje se ukládat nahrané soubory mimo document-root webového serveru a poskytovat je přes samostatný kontrolér s ověřením přístupových práv.

Často kladené otázky

Čím se multipart/form-data liší od application/x-www-form-urlencoded?

multipart/form-data přenáší každé pole formuláře jako samostatný blok s vlastními hlavičkami a podporuje binární soubory bez kódování. application/x-www-form-urlencoded kóduje všechna data do řetězce kompatibilního s URI (klíč=hodnota&klíč2=hodnota2) a nepodporuje soubory přímo — ty musí být zakódovány do base64.

Jaká je maximální velikost souboru pro Multipart Upload?

Protokol HTTP neomezuje velikost multipart požadavku, ale v praxi jsou limity nastaveny serverem. Nginx ve výchozím nastavení omezuje na 1 MB, Apache — na 2 MB, Spring Boot — na 1 MB. Pro nahrávání velkých souborů nakonfigurujte client_max_body_size (Nginx) nebo spring.servlet.multipart.max-file-size (Spring Boot) na požadovanou hodnotu — například 100 MB.

Lze odeslat více souborů v jednom multipart požadavku?

Ano, multipart/form-data podporuje více souborů v jednom požadavku. Každý soubor je přenášen jako samostatná část s vlastním Content-Disposition a Content-Type. HTML formuláře používají atribut multiple pro input type="file". V OkHttp se pro každý soubor volá addFormDataPart, v Alamofire — append pro každý soubor.

K čemu slouží boundary v multipart požadavku?

Boundary je jedinečný řetězec, který odděluje části složeného požadavku a umožňuje serveru určit, kde jedna část končí a druhá začíná. Je generován klientem a uveden v hlavičce Content-Type. Bez boundary by server nemohl rozdělit vícesložkový požadavek na jednotlivá pole a soubory.

Jak zkontrolovat typ nahraného souboru na serveru?

Nespoléhejte se na příponu souboru nebo Content-Type z požadavku — útočník je může zfalšovat. Zkontrolujte typ MIME pomocí magic bytes (první bajty souboru): knihovny Apache Tika v Javě, libmagic v C/C++, příkaz file v Linuxu, nebo vestavěné nástroje frameworků — Files.probeContentType() v Javě, mimetypes v Pythonu.

Shrnutí

  • Multipart Upload — mechanismus přenosu několika heterogenních částí v jednom HTTP požadavku s oddělením pomocí boundary.
  • multipart/form-data — standardní typ MIME pro nahrávání souborů přes webové formuláře a mobilní aplikace, podporuje binární přenos bez kódování.
  • Každá část požadavku obsahuje vlastní hlavičky Content-Disposition a Content-Type, což umožňuje přenášet pole různých typů v jednom požadavku.
  • Boundary — jedinečný oddělovací řetězec, automaticky generovaný klientem a nesmí se vyskytovat v přenášených datech.
  • Výhody — jeden požadavek místo mnoha, binární přenos bez kódování base64, podpora souborů libovolné velikosti (při správné konfiguraci serveru).
  • Omezení — limity velikosti na serveru, timeouty při nahrávání velkých souborů, riziko OutOfMemoryError bez streamovacího zpracování.
  • Bezpečnost — kontrolujte MIME typ podle obsahu souboru, ne podle přípony, ukládejte soubory mimo document-root a skenujte je antivirem.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také