Saltar al contenido

application/x-www-form-urlencoded o multipart/form-data?

Nuestros mejores investigadores agotaron sus provisiones de café, buscando diariamente por la respuesta, hasta que Alan encontró la respuesta en Gitea así que hoy la comparte con nosotros.

Solución:

TL;DR

Resumen; si tiene datos binarios (no alfanuméricos) (o una carga útil de tamaño significativo) para transmitir, use multipart/form-data. De lo contrario, utilice application/x-www-form-urlencoded.


Los tipos MIME que mencionas son los dos Content-Type encabezados para solicitudes HTTP POST que los agentes de usuario (navegadores) deben admitir. El propósito de ambos tipos de solicitudes es enviar una lista de pares de nombre/valor al servidor. Según el tipo y la cantidad de datos que se transmiten, uno de los métodos será más eficaz que el otro. Para entender por qué, hay que mirar lo que cada uno está haciendo debajo de las sábanas.

Para application/x-www-form-urlencodedel cuerpo del mensaje HTTP enviado al servidor es esencialmente una consulta gigante string — los pares de nombre/valor están separados por el ampersand (&), y los nombres están separados de los valores por el símbolo igual (=). Un ejemplo de esto sería:

MyVariableOne=ValueOne&MyVariableTwo=ValueTwo

Según la especificación:

[Reserved and] los caracteres no alfanuméricos se reemplazan por ‘%HH’, un signo de porcentaje y dos dígitos hexadecimales que representan el código ASCII del carácter

Eso significa que por cada byte no alfanumérico que existe en uno de nuestros valores, se necesitarán tres bytes para representarlo. Para archivos binarios grandes, triplicar la carga útil será muy ineficiente.

Ahí es donde multipart/form-data entra. Con este método de transmisión de pares de nombre/valor, cada par se representa como una “parte” en un mensaje MIME (como se describe en otras respuestas). Las partes están separadas por un determinado string límite (elegido específicamente para que este límite string no ocurre en ninguna de las cargas útiles de “valor”). Cada parte tiene su propio conjunto de encabezados MIME como Content-Typey particularmente Content-Disposition, que puede dar a cada parte su “nombre”. La pieza de valor de cada par nombre/valor es la carga útil de cada parte del mensaje MIME. La especificación MIME nos brinda más opciones al representar el valor de la carga útil: podemos elegir una codificación más eficiente de datos binarios para ahorrar ancho de banda (por ejemplo, base 64 o incluso binario sin procesar).

¿Por qué no usar? multipart/form-data ¿todo el tiempo? Para valores alfanuméricos cortos (como la mayoría de los formularios web), la sobrecarga de agregar todos los encabezados MIME superará significativamente cualquier ahorro de una codificación binaria más eficiente.

¡LEA AL MENOS EL PRIMER PARA AQUÍ!

Sé que esto es 3 años demasiado tarde, pero la respuesta (aceptada) de Matt está incompleta y eventualmente lo meterá en problemas. los key aquí está eso, si eliges usar multipart/form-datael límite debe no aparecen en el archivo de datos que finalmente recibe el servidor.

Esto no es un problema para application/x-www-form-urlencodedporque no hay límite. x-www-form-urlencoded también puede manejar siempre datos binarios, por el simple recurso de convertir un byte arbitrario en tres 7BIT bytes Ineficiente, pero funciona (y tenga en cuenta que el comentario sobre no poder enviar nombres de archivo y datos binarios es incorrecto; simplemente lo envía como otro keypar /valor).

el problema con multipart/form-data es que el separador de límites no debe estar presente en los datos del archivo (consulte RFC 2388; la sección 5.2 también incluye una excusa poco convincente para no tener un tipo MIME agregado adecuado que evite este problema).

Entonces, a primera vista, multipart/form-data no tiene valor alguno en ninguna carga de archivos, binarios o de otro tipo. Si no elige su límite correctamente, entonces usted voluntad eventualmente tendrá un problema, ya sea que esté enviando texto sin formato o binario sin procesar: el servidor encontrará un límite en el lugar equivocado y su archivo se truncará o el POST fallará.

los key es elegir una codificación y un límite de modo que los caracteres de límite seleccionados no puedan aparecer en la salida codificada. Una solución simple es usar base64 (hacer no usar binario sin formato). En base64, 3 bytes arbitrarios se codifican en cuatro caracteres de 7 bits, donde el conjunto de caracteres de salida es [A-Za-z0-9+/=] (es decir, alfanuméricos, ‘+’, ‘/’ o ‘=’). = es un caso especial, y solo puede aparecer al final de la salida codificada, como un solo = o un doble ==. Ahora, elija su límite como ASCII de 7 bits string que no puede aparecer en base64 producción. Muchas opciones que ve en la red fallan en esta prueba: los documentos de formularios MDN, por ejemplo, usan “blob” como límite al enviar datos binarios, lo que no es bueno. Sin embargo, algo como “!blob!” nunca aparecerá en base64 producción.

No creo que HTTP esté limitado a POST en varias partes o x-www-form-urlencoded. El encabezado de tipo de contenido es ortogonal al método HTTP POST (puede completar el tipo MIME que más le convenga). Este también es el caso de las típicas aplicaciones web basadas en representación HTML (por ejemplo, json payload se volvió muy popular para transmitir payload para solicitudes ajax).

Con respecto a Restful API sobre HTTP, los tipos de contenido más populares con los que me puse en contacto son application/xml y application/json.

aplicación/xml:

  • tamaño de datos: XML muy detallado, pero generalmente no es un problema cuando se usa compresión y se piensa que el caso de acceso de escritura (por ejemplo, a través de POST o PUT) es mucho más raro que el acceso de lectura (en muchos casos es <3% de todo el tráfico ). Rara vez hubo casos en los que tuve que optimizar el rendimiento de escritura
  • existencia de caracteres no ascii: puede usar utf-8 como codificación en XML
  • existencia de datos binarios: necesitaría usar la codificación base64
  • datos de nombre de archivo: puede encapsular este campo interior en XML

aplicación/json

  • tamaño de datos: más compacto menos que XML, todavía texto, pero puede comprimir
  • caracteres no ascii: json es utf-8
  • datos binarios: base64 (ver también json-binary-question)
  • datos de nombre de archivo: encapsular como propia sección de campo dentro de json

datos binarios como recurso propio

Intentaría representar los datos binarios como un activo/recurso propio. Agrega otra llamada pero desacopla mejor las cosas. Imágenes de ejemplo:

POST /images
Content-type: multipart/mixed; boundary="xxxx" 
... multipart data

201 Created
Location: http://imageserver.org/../foo.jpg

En recursos posteriores, podría simplemente incorporar el recurso binario como enlace:


 ...
 

Te invitamos a asentar nuestra función poniendo un comentario y dejando una puntuación te damos la bienvenida.

¡Haz clic para puntuar esta entrada!
(Votos: 2 Promedio: 4.5)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *