Multipart Upload no desenvolvimento web: essência, estrutura e como funciona multipart/form-data

Autor: IT Sectr Publicado: 2026-03-10 Tempo de leitura: 9 min

Multipart Upload é um mecanismo HTTP que permite transferir várias partes heterogêneas de dados em uma única requisição, incluindo campos de texto e arquivos binários. Cada parte é separada por uma string de limite única e possui seu próprio cabeçalho Content-Type. De acordo com MDN Web Docs, 2025, multipart/form-data é o formato padrão para upload de arquivos através de formulários HTML e é amplamente utilizado em aplicações web e móveis para enviar imagens, documentos e outros arquivos ao servidor.

Pontos principais

  • Multipart Upload — transferência de múltiplas partes de dados em uma única requisição HTTP separadas por um boundary.
  • multipart/form-data — o tipo MIME padrão para upload de arquivos de formulários HTML e aplicações móveis.
  • Boundary — uma string única que separa as partes de uma requisição composta, gerada automaticamente pelos clientes HTTP.
  • Cada parte contém cabeçalhos Content-Disposition e Content-Type descrevendo o nome do campo e o tipo de arquivo.
  • Multipart Upload é mais eficiente que múltiplas requisições — um POST substitui N chamadas separadas ao servidor.

O que é Multipart Upload?

Multipart Upload é um método de transferência de dados via protocolo HTTP no qual o corpo da requisição consiste em várias partes logicamente separadas. Cada parte pode conter dados de um tipo diferente: um campo de formulário de texto, um arquivo binário, um objeto JSON ou uma imagem. Todas as partes são empacotadas em uma única requisição POST, eliminando a necessidade de enviar N chamadas HTTP separadas. Multipart Upload é uma parte essencial dos formulários web e APIs de upload de arquivos.

O formato multipart foi definido na especificação RFC 2046 como parte do padrão MIME para mensagens de email, e posteriormente adaptado para HTTP na RFC 1867. Hoje, o desenvolvimento web usa quase exclusivamente multipart/form-data — um dos subtipos multipart projetados para formulários contendo arquivos. Outros subtipos — multipart/mixed (para anexos arbitrários) e multipart/byteranges (para download parcial de arquivos) — são usados com muito menos frequência.

A diferença fundamental entre multipart e application/x-www-form-urlencoded é que este último codifica todos os dados em uma string compatível com URI e não suporta arquivos binários. Multipart/form-data, por outro lado, transmite cada arquivo em sua forma binária original sem codificação, o que é mais eficiente e não perde precisão. O tamanho da requisição com multipart é sempre 5-15% maior que a soma dos tamanhos dos arquivos devido à sobrecarga dos cabeçalhos das partes e limites.

Quando o Multipart Upload é usado

Multipart Upload é usado em todos os lugares onde o upload de arquivos é necessário: avatares e fotos de perfil em redes sociais, anexos em mensageiros, documentos em sistemas CRM, imagens de produtos em lojas online. Em aplicações móveis, o Multipart Upload é usado para enviar arquivos de mídia ao servidor — fotos da câmera do dispositivo, gravações de voz, clipes de vídeo. De acordo com a Cloudflare Research, cerca de 15% de todas as requisições POST na web usam multipart/form-data.

Diferença entre multipart e chunked transfer

Multipart Upload e Chunked Transfer são mecanismos diferentes. Multipart divide uma requisição em partes com significado (campos e arquivos), enquanto Chunked Transfer divide um fluxo de dados em fragmentos para transmissão sem conhecer o tamanho total. Multipart pode ser transmitido dentro de Chunked Transfer: o servidor envia uma resposta multipart em partes sem conhecer seu tamanho completo. Esses mecanismos não entram em conflito e resolvem problemas diferentes em níveis diferentes.

Como funciona multipart/form-data

Quando um navegador envia um formulário com o atributo enctype="multipart/form-data", ele constrói o corpo da requisição no formato multipart. Cada campo do formulário se torna um bloco separado, separado dos outros por uma string de limite (boundary). O limite é gerado automaticamente e é uma sequência única de caracteres que garante não aparecer dentro dos dados. O cliente adiciona este limite ao cabeçalho Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryX7K.

Cada bloco começa com --boundary e contém cabeçalhos Content-Disposition com o nome do campo (name) e, para arquivos, o nome original do arquivo (filename). Após uma linha em branco vêm os dados do campo ou o conteúdo do arquivo em forma binária. A requisição termina com a string --boundary--. O servidor analisa o fluxo recebido: primeiro encontra o limite, depois extrai os cabeçalhos de cada parte, determina o tipo de dados e os passa ao manipulador do formulário ou controlador da API.

De acordo com IETF RFC 7578, multipart/form-data não requer especificar um charset para cada parte, já que os campos de texto são considerados em UTF-8 e as partes binárias contêm arquivos em sua codificação original. O tamanho de uma parte não é limitado pelo protocolo — os limites são configurados no nível do servidor: por exemplo, no Nginx através de client_max_body_size, no Spring Boot através de spring.servlet.multipart.max-file-size.

Formato do boundary e sua geração

Boundary é uma string única que não deve aparecer nos dados transmitidos. Geralmente começa com um prefixo (por exemplo, ----WebKitFormBoundary ou ----Boundary) e contém caracteres aleatórios. Navegadores e clientes HTTP geram o boundary automaticamente. O comprimento do boundary não deve exceder 70 caracteres de acordo com RFC 2046. Cada parte é separada pela string --boundary\r\n, e o final da requisição é marcado por --boundary--\r\n.

Estrutura de uma requisição multipart

Uma requisição multipart tem uma estrutura estrita definida pelos padrões MIME e HTTP. O cabeçalho da requisição define Content-Type: multipart/form-data com um parâmetro boundary. O corpo da requisição consiste em uma sequência de partes, cada uma contendo seus próprios cabeçalhos e corpo. Os cabeçalhos da parte incluem Content-Disposition (obrigatório) e Content-Type (opcional — para arquivos). Uma linha em branco entre os cabeçalhos da parte e seus dados é obrigatória.

ElementoExemploObrigatoriedade
Content-Typemultipart/form-data; boundary=---Bnd123Sim
Delimitador de parte---Bnd123Sim (antes de cada parte)
Content-Dispositionform-data; name="avatar"; filename="photo.jpg"Sim
Content-Type da parteimage/jpegPara arquivos
Corpo da parte[dados binários da imagem]Sim
Limite final---Bnd123--Sim (fim da requisição)

Exemplo de requisição multipart

Considere um exemplo real de uma requisição multipart enviando um campo de texto e um arquivo de imagem. O cliente forma o cabeçalho Content-Type com um boundary único. O corpo da requisição contém sequencialmente todos os campos do formulário. Ao receber, o servidor analisa essas partes e fornece ao desenvolvedor acesso a cada campo como um objeto separado. Essa abordagem permite processar formulários complexos com arquivos em uma única chamada HTTP.

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

Analisando uma resposta multipart no servidor

No lado do servidor, a requisição multipart é analisada pelo framework ou manualmente. No Spring Boot, basta a anotação @RequestParam("avatar") MultipartFile file, e o framework extrai automaticamente o arquivo da requisição multipart. No Ktor em Kotlin, usa-se receiveMultipart(); no Express.js — o middleware multer. O servidor obtém acesso a cada campo do formulário e a cada arquivo carregado de forma independente, salva o arquivo em disco ou armazenamento em nuvem e retorna uma URL ou identificador ao cliente.

Vantagens do upload multicomponente

Multipart Upload oferece várias vantagens principais sobre métodos alternativos de transferência de dados. Uma requisição em vez de muitas — todos os campos do formulário e arquivos são transmitidos em uma única chamada HTTP, reduzindo a carga na rede e no servidor. Não é necessário abrir N conexões para carregar N arquivos — tudo é empacotado em um único POST. Isso é especialmente importante para aplicações móveis, onde cada conexão HTTP significa latência e consumo de bateria.

Transferência binária sem codificação — ao contrário de application/x-www-form-urlencoded, onde dados binários são codificados em base64 (aumentando o tamanho em 33%), multipart/form-data transmite arquivos em sua forma binária original. Isso é mais eficiente em tamanho e velocidade. Para arquivos grandes acima de 10 MB, a diferença se torna crítica: uma requisição multipart será 30% menor que uma requisição codificada em URL com o mesmo arquivo.

Estrutura arbitrária — multipart permite combinar campos de diferentes tipos em qualquer ordem. Um formulário pode conter campos de texto, vários arquivos, dados JSON e campos ocultos simultaneamente. Cada parte tem seu próprio Content-Type, permitindo misturar dados de texto e binários. Para comparação: a codificação base64 adiciona 33% ao tamanho, enquanto multipart adiciona apenas cerca de 5-15% para cabeçalhos de serviço.

Comparação do multipart com outros formatos de transferência

De acordo com a pesquisa do HTTP Archive, 2025, multipart/form-data é usado em 94% dos casos de upload de arquivos na web. Alternativas — base64 em JSON (4%) e transferência direta via WebSocket (2%). JSON com base64 é conveniente para APIs onde todos os outros dados também estão em JSON, mas é ineficiente para arquivos grandes. WebSocket é adequado para dados em tempo real, mas não é suportado por todas as infraestruturas HTTP. Multipart continua sendo o padrão para upload de arquivos devido à sua simplicidade e eficiência.

Multipart Upload no desenvolvimento móvel

Em aplicações móveis, Multipart Upload é usado para enviar conteúdo multimídia dos dispositivos dos usuários: fotos da galeria, capturas de câmera, gravações de voz, arquivos de documentos. No Android, a abordagem padrão é OkHttp com MultipartBody.Builder, que permite formar facilmente requisições multipart. Retrofit também suporta multipart através das anotações @Multipart e @Part. O desenvolvedor especifica o tipo de dados para cada parte, e o cliente HTTP gera automaticamente os cabeçalhos corretos.

No iOS, as mesmas tarefas são resolvidas com URLSession com um HTTPBodyStream personalizado ou através do Alamofire com multipartFormData. Alamofire fornece um método conveniente upload(multipartFormData:) para enviar requisições multipart. Em ambas as plataformas, é importante considerar o tamanho dos arquivos carregados — para arquivos grandes (mais de 10-20 MB), recomenda-se usar upload em segundo plano para que o aplicativo não termine ao ser minimizado. No Android, isso é feito através do DownloadManager ou WorkManager; no iOS, através do URLSession com configuração de fundo.

Ao carregar arquivos em aplicações móveis, o estado da rede deve ser considerado. Connectivity Manager no Android ajuda a determinar se Wi-Fi ou dados móveis estão disponíveis e escolher o momento ideal para o upload. Para arquivos grandes como vídeos, recomenda-se adiar o upload até conectar-se ao Wi-Fi para não consumir os dados móveis do usuário. WorkManager no Android permite definir tais restrições através do NetworkType.UNMETERED.

Otimização de upload: compressão e redimensionamento

Antes de enviar um arquivo via Multipart Upload, as aplicações móveis frequentemente comprimem e redimensionam a imagem. A compressão JPEG com qualidade de 85% reduz o tamanho do arquivo em 3-5 vezes sem perda perceptível de qualidade para visualização na tela. Redimensionar a imagem para 1920px no lado maior reduz ainda mais o tamanho. No Android, isso é feito com Bitmap.compress(); no iOS, com UIImageJPEGRepresentation com parâmetro de compressão 0.85. Essa otimização acelera o upload e economiza dados móveis.

Erros e limitações do Multipart Upload

O erro mais comum no Multipart Upload é exceder o limite de tamanho da requisição no servidor. Por padrão, o Nginx limita o tamanho do corpo da requisição a 1 MB (client_max_body_size), e o Tomcat a 2 MB (maxSwallowSize). Se o desenvolvedor não aumentar esses limites, o servidor retornará um erro 413 Request Entity Too Large. A solução é configurar explicitamente o tamanho máximo de upload no servidor e mostrar um aviso no cliente se o arquivo exceder o tamanho permitido.

O segundo problema é o manuseio incorreto de requisições multipart durante o streaming do corpo. Alguns servidores tentam carregar toda a requisição multipart na memória antes de analisá-la, o que leva a OutOfMemoryError para arquivos grandes. Servidores modernos (Nginx, Spring Boot, Ktor) suportam análise em streaming de multipart, onde cada parte é processada à medida que chega. O desenvolvedor deve garantir que o servidor esteja configurado para processamento em streaming de requisições multipart.

A terceira categoria de problemas são os timeouts ao carregar arquivos grandes. Clientes HTTP têm configurações de readTimeout e connectTimeout que podem disparar durante uploads longos de arquivos acima de 50-100 MB. A solução é aumentar os timeouts para endpoints de upload ou usar chunked transfer encoding dentro do multipart. Em dispositivos móveis, também é importante lidar com a interrupção do upload e implementar retomada (resume) em caso de perda de conexão.

Segurança do Multipart Upload

O upload de arquivos via multipart é um dos endpoints mais vulneráveis de uma aplicação web. Um atacante pode carregar um script executável renomeando-o para image.jpg. O servidor deve verificar o tipo MIME do arquivo carregado não pela extensão mas pelo conteúdo (magic bytes), limitar os tipos permitidos e escanear os arquivos com antivírus. Recomenda-se armazenar os arquivos carregados fora do document-root do servidor web e servi-los através de um controlador separado com verificação de permissões de acesso.

Perguntas frequentes

Como multipart/form-data difere de application/x-www-form-urlencoded?

multipart/form-data transmite cada campo do formulário como um bloco separado com seus próprios cabeçalhos e suporta arquivos binários sem codificação. application/x-www-form-urlencoded codifica todos os dados em uma string compatível com URI (chave=valor&chave2=valor2) e não suporta arquivos diretamente — eles precisam ser codificados em base64.

Qual é o tamanho máximo de arquivo para Multipart Upload?

O protocolo HTTP não limita o tamanho de uma requisição multipart, mas na prática os limites são definidos pelo servidor. Nginx por padrão limita a 1 MB, Apache a 2 MB, Spring Boot a 1 MB. Para carregar arquivos grandes, configure client_max_body_size (Nginx) ou spring.servlet.multipart.max-file-size (Spring Boot) para o valor desejado — por exemplo, 100 MB.

Vários arquivos podem ser enviados em uma única requisição multipart?

Sim, multipart/form-data suporta vários arquivos em uma única requisição. Cada arquivo é transmitido como uma parte separada com seu próprio Content-Disposition e Content-Type. Formulários HTML usam o atributo multiple para input type="file". No OkHttp, addFormDataPart é chamado para cada arquivo; no Alamofire, append é chamado para cada arquivo.

Por que um boundary é necessário em uma requisição multipart?

Boundary é uma string única que separa as partes de uma requisição composta e permite ao servidor determinar onde uma parte termina e outra começa. É gerado pelo cliente e especificado no cabeçalho Content-Type. Sem um boundary, o servidor não pode analisar uma requisição multicomponente em campos e arquivos individuais.

Como verificar o tipo de arquivo carregado no servidor?

Não confie na extensão do arquivo ou no Content-Type da requisição — um atacante pode falsificá-los. Verifique o tipo MIME através de magic bytes (os primeiros bytes do arquivo): Apache Tika em Java, libmagic em C/C++, o comando file no Linux, ou ferramentas integradas do framework — Files.probeContentType() em Java, mimetypes em Python.

Resumo

  • Multipart Upload — um mecanismo para transferir várias partes heterogêneas em uma única requisição HTTP separadas por um boundary.
  • multipart/form-data — o tipo MIME padrão para upload de arquivos através de formulários web e aplicações móveis, suporta transferência binária sem codificação.
  • Cada parte da requisição contém seus próprios cabeçalhos Content-Disposition e Content-Type, permitindo enviar campos de diferentes tipos em uma única requisição.
  • Boundary — uma string delimitadora única, gerada automaticamente pelo cliente, que não deve aparecer nos dados transmitidos.
  • Vantagens — uma requisição em vez de muitas, transferência binária sem codificação base64, suporte para arquivos de qualquer tamanho (com configuração adequada do servidor).
  • Limitações — limites de tamanho no servidor, timeouts ao carregar arquivos grandes, risco de OutOfMemoryError sem processamento em streaming.
  • Segurança — verifique o tipo MIME pelo conteúdo do arquivo, não pela extensão; armazene arquivos fora do document-root e escaneie-os em busca de vírus.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também