Skip to content

Calcular com precisão o overhead de multipart/form-data

Categoria:HTTP・Comunicação
Este artigo está disponível atualmente apenas em japonês. As versões traduzidas serão publicadas sequencialmente.

Você já teve a experiência de 「o arquivo tem 9MB, mas aparece erro 413」 em testes de limite de tamanho de upload? Uma das causas é o overhead de <code>multipart/form-data</code>. Ao fazer upload de arquivo via formulário HTML, o corpo da requisição HTTP contém não apenas o arquivo em si, mas também metadados adicionais. Este artigo explica o método preciso de cálculo desse overhead e pontos de atenção durante os testes.

Estrutura de multipart/form-data

O <code>multipart/form-data</code> definido em RFC 2046 possui uma estrutura em que cada parte é separada por uma string boundary. O corpo da solicitação HTTP real fica assim.

POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123
Content-Length: 10000xyz

------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="file"; filename="test.png"
Content-Type: image/png

[ファイルのバイナリデータ]
------WebKitFormBoundaryABC123--

Detalhamento do overhead

A sobrecarga de uma solicitação típica de upload de arquivo é composta pelos seguintes elementos.

ElementoExemploNúmero de bytes (estimativa)
boundary inicial------WebKitFormBoundaryABC123\r\nAproximadamente 40–80 B
Cabeçalho Content-DispositionContent-Disposition: form-data; name="file"; filename="test.png"\r\nAproximadamente 60–120 B
Cabeçalho Content-TypeContent-Type: image/png\r\nAproximadamente 25–50 B
Linha em branco (fim do header)\r\n2 B
Quebra de linha no final da parte\r\n2 B
boundary de término------WebKitFormBoundaryABC123--\r\nAproximadamente 42–82 B
<strong>Overhead total</strong><strong>Cerca de 200–350 B</strong>

Para um formulário simples com apenas um arquivo, o overhead é aproximadamente <strong>200〜400 bytes</strong>. Se houver campos de formulário adicionais (como entradas de texto), aumentará proporcionalmente, mas geralmente fica dentro de centenas de bytes até alguns KB.

Por que ocorre o erro 413

O <code>client_max_body_size</code> do Nginx limita o tamanho do <strong>corpo da solicitação inteira</strong>. Isso significa que o valor configurado deve incluir overhead.

# 10MiB のファイルをアップロードさせたい場合
# オーバーヘッド(約1KB)を考慮して少し大きめに設定
client_max_body_size 11m;  # MiB単位: 11 MiB = 11,534,336 バイト

Em PHP, você precisa configurar dois valores: <code>upload_max_filesize</code> (arquivo individual) e <code>post_max_size</code> (corpo POST inteiro).

; php.ini
upload_max_filesize = 10M   ; ファイル単体の上限: 10 MiB
post_max_size = 11M         ; POSTボディ全体の上限: 11 MiB(オーバーヘッド分を加算)

Método para medir overhead preciso

Se você quiser conhecer o overhead real com precisão, pode enviar requisições com curl e medir o tamanho da requisição.

# ファイルのバイト数を確認
wc -c test-10mb.png
# → 10485760 test-10mb.png

# curl でアップロードしてリクエストサイズを確認
curl -X POST https://example.com/upload \
  -F "file=@test-10mb.png" \
  -w "リクエストボディサイズ: %{size_upload} バイト\n" \
  -o /dev/null -s
# → リクエストボディサイズ: 10486062 バイト(差: 302バイト)

Diferenças com a codificação Base64

No caso de <code>multipart/form-data</code>, os dados binários do arquivo são enviados como estão (sem codificação Base64). A codificação Base64 é necessária ao enviar dados binários com <code>application/x-www-form-urlencoded</code> ou ao enviar arquivos no corpo JSON (<code>data:image/png;base64,...</code>).

Método de transmissãoOverheadUso
multipart/form-data (Formulário HTML)Centenas de B a alguns KBUpload de arquivo comum
JSON + Base64Aumento de aproximadamente 33%Envio de arquivo via API
application/octet-stream(PUT)Quase zeroURLs pré-assinadas do S3 e similares

Pontos importantes para teste

  • Determine se a verificação de limite do servidor é 「arquivo individual」 ou 「corpo da solicitação inteira」
  • Como o Nginx limita solicitações em frente do PHP, também verifique <code>client_max_body_size</code> do Nginx
  • Upload simultâneo de múltiplos arquivos aumenta o overhead
  • O overhead inclui também campos de formulário adicionais (nome, comentários, etc.)

Usando os <a href="/ja/files/threshold/">arquivos para teste de limite</a> do DevLab, você pode verificar o comportamento de upload real com tamanhos de arquivo próximos aos limites. Valide junto com as configurações de Nginx/Apache/PHP.

Resumo

  • O overhead de <code>multipart/form-data</code> é <strong>aproximadamente 200-400 bytes</strong> (para um arquivo)
  • Como o <code>client_max_body_size</code> do Nginx limita o corpo inteiro da solicitação, configure um valor um pouco maior que o limite de arquivo
  • PHP requer a configuração de dois parâmetros: <code>upload_max_filesize</code> (arquivo individual) e <code>post_max_size</code> (corpo POST inteiro)
  • Ao enviar com JSON + Base64, o tamanho do arquivo aumenta cerca de 33%

Arquivo de teste disponível para usar neste artigo

  • → <a href="/ja/files/threshold/" class="text-primary-600 dark:text-primary-400 hover:underline">Lista de arquivos de teste de limite (9.9MB / 10MB / 10.1MB)</a>
  • → <a href="/ja/files/images/png/" class="text-primary-600 dark:text-primary-400 hover:underline">Lista de arquivos de teste de imagem PNG</a>

Artigos relacionados

  • → <a href="/ja/blog/how-to-test-upload-limit/" class="text-primary-600 dark:text-primary-400 hover:underline">Como testar corretamente o limite de upload de arquivo</a>
  • → <a href="/ja/blog/mb-vs-mib-file-size/" class="text-primary-600 dark:text-primary-400 hover:underline">MB e MiB são diferentes! As armadilhas das unidades de tamanho de arquivo</a>