Multipart Upload in Web Development: Essence, Structure and How multipart/form-data Works

Author: IT Sectr Published: 2026-03-10 Reading time: 9 min

Multipart Upload is an HTTP mechanism that allows transferring several heterogeneous parts of data in a single request, including text fields and binary files. Each part is separated by a unique boundary string and has its own Content-Type header. According to MDN Web Docs, 2025, multipart/form-data is the standard format for uploading files via HTML forms and is widely used in web and mobile applications for sending images, documents, and other files to the server.

Key Takeaways

  • Multipart Upload — transferring multiple data parts in a single HTTP request separated by a boundary.
  • multipart/form-data — the standard MIME type for uploading files from HTML forms and mobile applications.
  • Boundary — a unique string separating the parts of a compound request, automatically generated by HTTP clients.
  • Each part contains Content-Disposition and Content-Type headers describing the field name and file type.
  • Multipart Upload is more efficient than multiple requests — one POST replaces N separate calls to the server.

What is Multipart Upload?

Multipart Upload is a method of data transfer via the HTTP protocol where the request body consists of several logically separated parts. Each part can contain data of a different type: a text form field, a binary file, a JSON object, or an image. All parts are packaged into a single POST request, replacing the need to send N separate HTTP calls. Multipart Upload is an essential part of web forms and file upload APIs.

The multipart format was defined in the RFC 2046 specification as part of the MIME standard for email messages, and was later adapted for HTTP in RFC 1867. Today, web development uses almost exclusively multipart/form-data — one of the multipart subtypes designed for forms containing files. Other subtypes — multipart/mixed (for arbitrary attachments) and multipart/byteranges (for partial file downloads) — are used much less frequently.

The fundamental difference between multipart and simple application/x-www-form-urlencoded is that the latter encodes all data into a URI-compatible string and does not support binary files. Multipart/form-data, on the other hand, transmits each file in its original binary form without encoding, which is more efficient and does not lose precision. The request size with multipart is always 5-15% larger than the sum of file sizes due to the overhead of part headers and boundaries.

When Multipart Upload Is Used

Multipart Upload is used everywhere file upload is required: avatars and profile photos in social networks, attachments in messengers, documents in CRM systems, product images in online stores. In mobile applications, Multipart Upload is used to send media files to the server — photos from the device camera, voice recordings, video clips. According to Cloudflare Research, about 15% of all POST requests on the web use multipart/form-data.

Difference Between Multipart and Chunked Transfer

Multipart Upload and Chunked Transfer are different mechanisms. Multipart divides a request into meaningful parts (fields and files), while Chunked Transfer splits a data stream into fragments for transmission without knowing the total size. Multipart can be transmitted inside Chunked Transfer: the server sends a multipart response in parts without knowing its full size. These mechanisms do not conflict and solve different problems at different levels.

How multipart/form-data Works

When a browser submits a form with the enctype="multipart/form-data" attribute, it constructs the request body in the multipart format. Each form field becomes a separate block, separated from others by a boundary string. The boundary is generated automatically and is a unique sequence of characters that is guaranteed not to appear within the data. The client adds this boundary to the Content-Type header: multipart/form-data; boundary=----WebKitFormBoundaryX7K.

Each block starts with --boundary and contains Content-Disposition headers with the field name (name) and, for files, the original filename (filename). After a blank line come the actual field data or file content in binary form. The request ends with the string --boundary--. The server parses the received stream: first it finds the boundary, then extracts the headers of each part, determines the data type, and passes them to the form handler or API controller.

According to IETF RFC 7578, multipart/form-data does not require specifying a charset for each part since text fields are assumed to be in UTF-8, and binary parts contain files in their original encoding. The size of one part is not limited by the protocol — limits are set at the server level: for example, in Nginx via client_max_body_size, in Spring Boot via spring.servlet.multipart.max-file-size.

Boundary Format and Its Generation

Boundary is a unique string that must not appear in the transmitted data. It usually starts with a prefix (e.g., ----WebKitFormBoundary or ----Boundary) and contains random characters. Browsers and HTTP clients generate the boundary automatically. The boundary length must not exceed 70 characters according to RFC 2046. Each part is separated by the string --boundary\r\n, and the end of the request is marked by --boundary--\r\n.

Multipart Request Structure

A multipart request has a strict structure defined by MIME and HTTP standards. The request header sets Content-Type: multipart/form-data with a boundary parameter. The request body consists of a sequence of parts, each containing its own headers and body. Part headers include Content-Disposition (mandatory) and Content-Type (optional — for files). A blank line between the part headers and its data is mandatory.

ElementExampleRequired
Content-Typemultipart/form-data; boundary=---Bnd123Yes
Part delimiter---Bnd123Yes (before each part)
Content-Dispositionform-data; name="avatar"; filename="photo.jpg"Yes
Part Content-Typeimage/jpegFor files
Part body[binary image data]Yes
Closing boundary---Bnd123--Yes (end of request)

Example of a Multipart Request

Consider a real example of a multipart request sending a text field and an image file. The client forms the Content-Type header with a unique boundary. The request body sequentially contains all form fields. When received, the server parses these parts and gives the developer access to each field as a separate object. This approach allows processing complex forms with files in a single HTTP call.

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("Uploaded: ${response.isSuccessful}")
    }
}

Parsing a Multipart Response on the Server

On the server side, the multipart request is parsed by the framework or manually. In Spring Boot, the @RequestParam("avatar") MultipartFile file annotation is sufficient, and the framework automatically extracts the file from the multipart request. In Ktor on Kotlin, receiveMultipart() is used; in Express.js, multer middleware. The server gains access to each form field and each uploaded file independently, saves the file to disk or cloud storage, and returns a URL or identifier to the client.

Advantages of Multi-Component Upload

Multipart Upload offers several key advantages over alternative data transfer methods. One request instead of many — all form fields and files are transmitted in a single HTTP call, reducing network and server load. There is no need to open N connections to upload N files — everything is packaged in one POST. This is especially important for mobile applications, where each HTTP connection means latency and battery drain.

Binary transfer without encoding — unlike application/x-www-form-urlencoded, where binary data is base64-encoded (increasing size by 33%), multipart/form-data transmits files in their original binary form. This is more efficient in both size and speed. For large files over 10 MB, the difference becomes critical: a multipart request will be 30% smaller than a URL-encoded request with the same file.

Arbitrary structure — multipart allows combining fields of different types in any order. A form can contain text fields, multiple files, JSON data, and hidden fields simultaneously. Each part has its own Content-Type, enabling mixing of text and binary data. For comparison: base64 encoding adds 33% to size, while multipart adds only about 5-15% for overhead headers.

Comparison of Multipart with Other Transfer Formats

According to HTTP Archive, 2025 research, multipart/form-data is used in 94% of file upload cases on the web. Alternatives — base64 in JSON (4%) and direct transfer via WebSocket (2%). JSON with base64 is convenient for APIs where all other data is also in JSON, but is inefficient for large files. WebSocket is suitable for real-time data but is not supported by all HTTP infrastructures. Multipart remains the standard for file uploads due to its simplicity and efficiency.

Multipart Upload in Mobile Development

In mobile applications, Multipart Upload is used to send media content from user devices: photos from the gallery, camera shots, voice recordings, document files. On Android, the standard approach is OkHttp with MultipartBody.Builder, which makes it easy to form multipart requests. Retrofit also supports multipart via @Multipart and @Part annotations. The developer specifies the data type for each part, and the HTTP client automatically generates the correct headers.

On iOS, the same tasks are handled by URLSession with a custom HTTPBodyStream or via Alamofire with multipartFormData. Alamofire provides a convenient upload(multipartFormData:) method for sending multipart requests. On both platforms, it is important to consider the size of uploaded files — for large files (over 10-20 MB), it is recommended to use background upload so the application does not terminate when minimized. On Android, this is done via DownloadManager or WorkManager; on iOS, via URLSession with background configuration.

When uploading files in mobile applications, network state must be considered. Connectivity Manager on Android helps determine whether Wi-Fi or mobile data is available and choose the optimal time for upload. For large files such as videos, it is recommended to defer upload until connected to Wi-Fi to avoid consuming the user's mobile data. WorkManager on Android allows setting such constraints via NetworkType.UNMETERED.

Upload Optimization: Compression and Resizing

Before sending a file via Multipart Upload, mobile applications often compress and resize the image. JPEG compression at 85% quality reduces file size by 3-5 times without noticeable quality loss for on-screen viewing. Resizing the image to 1920px on the longest side further reduces size. On Android, this is done using Bitmap.compress(); on iOS, using UIImageJPEGRepresentation with a compression parameter of 0.85. Such optimization speeds up upload and saves mobile data.

Multipart Upload Errors and Limitations

The most common error with Multipart Upload is exceeding the server request size limit. By default, Nginx limits request body size to 1 MB (client_max_body_size), and Tomcat to 2 MB (maxSwallowSize). If the developer does not increase these limits, the server returns a 413 Request Entity Too Large error. The solution is to explicitly set the maximum upload size on the server and show a warning on the client if the file exceeds the allowed size.

The second problem is incorrect handling of multipart requests during body streaming. Some servers try to load the entire multipart request into memory before parsing, which leads to OutOfMemoryError for large files. Modern servers (Nginx, Spring Boot, Ktor) support streaming multipart parsing, where each part is processed as it arrives. The developer must ensure the server is configured for streaming processing of multipart requests.

The third category of problems is timeouts when uploading large files. HTTP clients have readTimeout and connectTimeout settings that can trigger during long uploads of files over 50-100 MB. The solution is to increase timeouts for upload endpoints or use chunked transfer encoding within multipart. On mobile devices, it is also important to handle upload interruption and implement resume on connection loss.

Multipart Upload Security

File upload via multipart is one of the most vulnerable endpoints of a web application. An attacker can upload an executable script by renaming it to image.jpg. The server must check the MIME type of the uploaded file not by extension but by content (magic bytes), limit allowed types, and scan files with an antivirus. It is recommended to store uploaded files outside the web server's document-root and serve them through a separate controller with access control checks.

Frequently Asked Questions

How is multipart/form-data different from application/x-www-form-urlencoded?

multipart/form-data transmits each form field as a separate block with its own headers and supports binary files without encoding. application/x-www-form-urlencoded encodes all data into a URI-compatible string (key=value&key2=value2) and does not support files directly — they have to be base64-encoded.

What is the maximum file size for Multipart Upload?

The HTTP protocol does not limit the size of a multipart request, but in practice limits are set by the server. Nginx defaults to 1 MB, Apache to 2 MB, Spring Boot to 1 MB. To upload large files, configure client_max_body_size (Nginx) or spring.servlet.multipart.max-file-size (Spring Boot) to the desired value — for example, 100 MB.

Can multiple files be sent in one multipart request?

Yes, multipart/form-data supports multiple files in a single request. Each file is transmitted as a separate part with its own Content-Disposition and Content-Type. HTML forms use the multiple attribute for input type="file". In OkHttp, addFormDataPart is called for each file; in Alamofire, append is called for each file.

Why is a boundary needed in a multipart request?

Boundary is a unique string that separates the parts of a compound request and allows the server to determine where one part ends and another begins. It is generated by the client and specified in the Content-Type header. Without a boundary, the server cannot parse a multi-component request into individual fields and files.

How to check the type of an uploaded file on the server?

Do not rely on the file extension or Content-Type from the request — an attacker can forge these. Check the MIME type via magic bytes (the first bytes of the file): Apache Tika on Java, libmagic on C/C++, the file command on Linux, or built-in framework tools — Files.probeContentType() on Java, mimetypes on Python.

Summary

  • Multipart Upload — a mechanism for transferring several heterogeneous parts in a single HTTP request separated by a boundary.
  • multipart/form-data — the standard MIME type for uploading files via web forms and mobile applications, supports binary transfer without encoding.
  • Each part of the request contains its own Content-Disposition and Content-Type headers, allowing fields of different types to be sent in one request.
  • Boundary — a unique delimiter string, automatically generated by the client, that must not appear in the transmitted data.
  • Advantages — one request instead of many, binary transfer without base64 encoding, support for files of any size (with proper server configuration).
  • Limitations — server size limits, timeouts during large file uploads, risk of OutOfMemoryError without streaming processing.
  • Security — check MIME type by file content, not by extension; store files outside the document-root and scan them for viruses.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also