aplicação/x-www-form-urlencoded ou multipart/form-data?

No HTTP existem duas maneiras de se colocar os dados no POST: aplicação/x-www-form-urlencoded' emultipart/form-data'. Eu entendo que a maioria dos navegadores só são capazes de carregar arquivos se o `multipart/form-data' for utilizado. Existe alguma orientação adicional quando utilizar um dos tipos de codificação em um contexto de API (sem browser envolvido)? Isto pode, por exemplo, ser baseado em:

  • tamanho de dados
  • existência de caracteres não-ASCII
  • existência sobre dados binários (não codificados)
  • a necessidade de transferir dados adicionais (como o nome do arquivo)

Basicamente não encontrei nenhuma orientação formal na web sobre o uso dos diferentes tipos de conteúdo até agora.

Solução

**TL;DR***

Resumo; se você tiver dados binários (não alfanuméricos) (ou uma carga útil de tamanho significativo) para transmitir, utilize multipart/form-data'. Caso contrário, utilizeapplication/x-www-form-urlencoded'.


Os tipos MIME que você menciona são os dois cabeçalhos `Content-Type' para pedidos POST HTTP que os agentes do usuário (navegadores) devem suportar. O propósito de ambos os tipos de requisições é enviar uma lista de pares nome/valor para o servidor. Dependendo do tipo e quantidade de dados a serem transmitidos, um dos métodos será mais eficiente do que o outro. Para entender o motivo, você tem que olhar para o que cada um está fazendo sob as capas.

Para application/x-www-form-urlencoded', o corpo da mensagem HTTP enviada para o servidor é essencialmente uma cadeia de consulta gigante -- os pares nome/valor são separados pelo ampersand (&), e os nomes são separados dos valores pelo símbolo de igual (=`). Um exemplo disso seria: 

MyVariableOne=ValueOne&MyVariableTwo=ValueTwo`

De acordo com a especificação:

[Reservado e] caracteres não alfanuméricos são substituídos por `%HH', um sinal de porcentagem e dois dígitos hexadecimais representando o código ASCII do caracter

Isso significa que para cada byte não alfanumérico que existe em um de nossos valores, são necessários três bytes para representá-lo. Para grandes arquivos binários, triplicar a carga útil vai ser altamente ineficiente.

Isso's em que "multi-parte/form-dados" entra. Com este método de transmissão de pares nome/valor, cada par é representado como um "part" em uma mensagem MIME (como descrito por outras respostas). As partes são separadas por um determinado limite de cadeia (escolhido especificamente para que essa cadeia não ocorra em nenhum dos "value" payloads). Cada parte tem seu próprio conjunto de cabeçalhos MIME como Content-Type', e particularmenteContent-Disposition', que pode dar a cada parte seu "name." A parte de valor de cada par nome/valor é a carga útil de cada parte da mensagem MIME. A especificação MIME nos dá mais opções ao representar a carga útil do valor -- podemos escolher uma codificação mais eficiente de dados binários para economizar largura de banda (por exemplo, base 64 ou mesmo binários brutos).

Por que não utilizar multipart/form-data o tempo todo? Para valores alfanuméricos curtos (como a maioria dos formulários web), a sobrecarga da adição de todos os cabeçalhos MIME vai superar significativamente qualquer economia com a codificação binária mais eficiente.

Comentários (16)

Eu não't acho que o HTTP está limitado ao POST em multipart ou x-www-form-urlencoded. O [Content-Type Header][1] é ortogonal ao método HTTP POST (você pode preencher o tipo MIME que lhe convém). Este é também o caso de webapps típicos baseados em representação HTML (por exemplo, a carga útil json tornou-se muito popular para transmitir carga útil para pedidos ajax).

Em relação ao Restful API sobre HTTP, os tipos de conteúdo mais populares com que entrei em contato são application/xml e application/json.

aplicação/xml:

  • tamanho dos dados: XML muito verboso, mas geralmente não é um problema quando se usa compressão e pensar que o caso de acesso de escrita (por exemplo, através de POST ou PUT) é muito mais raro como acesso de leitura (em muitos casos é
Comentários (3)

Concordo com muito do que o Manuel disse. Na verdade, os seus comentários referem-se a esta url...

http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4

... o que diz:

O tipo de conteúdo " application/x-www-form-urlencoded" é ineficiente para o envio de grandes quantidades de dados binários ou texto contendo caracteres não-ASCII. O tipo de conteúdo " multipart/form-data" deve ser usado para enviar formulários que contêm ficheiros, dados nãoASCII, e dados binários.

No entanto, para mim resumir-se-ia ao suporte de ferramentas/enquadramento.

  • Que ferramentas e estruturas você espera que os seus utilizadores de API estejam a construir as suas aplicações com?
  • Eles têm estruturas ou componentes que eles podem usar que favorecem um método em detrimento do Outro?

Se você tiver uma idéia clara dos seus usuários, e como eles'farão uso da sua API, então isso o ajudará a decidir. Se você tornar o upload de arquivos difícil para seus usuários de API, então eles'irão se afastar, de você'irão gastar muito tempo para apoiá-los.

Secundário a isto seria o suporte da ferramenta que VOCÊ tem para escrever seu API e como é fácil para você acomodar um mecanismo de upload sobre o outro.

Comentários (2)