Quiero hacer una pregunta sobre el multipart/form-data
. En la cabecera HTTP, encuentro que el Content-Type: multipart/form-data; boundary=???
.
¿El usuario puede definir libremente el tipo de datos? ¿O se genera a partir del HTML? ¿Es posible definir el campo "abcdefg"? = abcdefg`?
¿es libre de ser definido por el usuario?
Sí.
¿o es suministrado por el HTML?
No. HTML no tiene nada que ver con eso. Lea a continuación.
¿Es posible que defina el
???
comoabcdefg
?
Sí.
Si quiere enviar los siguientes datos al servidor web:
name = John
age = 12
usando application/x-www-form-urlencoded
sería así:
name=John&age=12
Como puede ver, el servidor sabe que los parámetros están separados por un ampersand &
. Si se requiere &
para un valor de parámetro, entonces debe ser codificado.
Entonces, ¿cómo sabe el servidor dónde empieza y termina un valor de parámetro cuando recibe una petición HTTP que utiliza multipart/form-data
?
Usando el límite, similar a &
.
Por ejemplo:
--XXX
Content-Disposition: form-data; name="name"
John
--XXX
Content-Disposition: form-data; name="age"
12
--XXX--
En ese caso, el valor límite es XXX
. Se especifica en la cabecera Content-Type
para que el servidor sepa cómo dividir los datos que recibe.
Por lo tanto, es necesario:
Utilizar un valor que no aparezca en los datos HTTP enviados al servidor.
Ser coherente y utilizar el mismo valor en todas las partes del mensaje de solicitud.
La respuesta exacta a la pregunta es: sí, puede utilizar un valor arbitrario para el parámetro boundary
, siempre que no exceda de 70 bytes de longitud y esté compuesto únicamente por caracteres 7 bits US-ASCII
(imprimibles).
Si utiliza uno de los tipos de contenido multipart/*
, en realidad está obligado a especificar el parámetro boundary
en la cabecera Content-Type
, de lo contrario el servidor (en el caso de una petición HTTP) no podrá analizar la carga útil.
Probablemente también quiera establecer el parámetro charset
a UTF-8
en su cabecera Content-Type
, a menos que pueda estar absolutamente seguro de que sólo se utilizará el conjunto de caracteres US-ASCII
en los datos de la carga útil.
Algunos extractos relevantes de la RFC2046:
4.1.2. Parámetro Charset: A diferencia de otros valores de parámetros, los valores del parámetro charset NO distinguen entre mayúsculas y minúsculas. El conjunto de caracteres por defecto, que debe asumirse en ausencia de un parámetro charset, es US-ASCII.
5.1. Tipo de medio multiparte Como se indica en la definición del campo Content-Transfer-Encoding [RFC 2045], no se permite ninguna codificación distinta de "7bit", "8bit", o "binaria" para entidades de tipo "multipart". Los delimitadores de frontera "multipart" y los campos de cabecera siempre se representan como US-ASCII de 7 bits en cualquier caso (aunque los campos de cabecera pueden codificar texto de cabecera que no sea US-ASCII, según la RFC 2047) y los datos dentro de las partes del cuerpo pueden codificarse parte por parte, con campos Content-Transfer-Encoding para cada parte del cuerpo apropiada.
El campo Content-Type para entidades multiparte requiere un parámetro, "boundary". La línea delimitadora se define entonces como una línea que consiste en dos caracteres de guión ("-", valor decimal 45) seguidos por el valor del parámetro boundary del campo de cabecera Content-Type, un espacio en blanco lineal opcional y un CRLF de terminación.
Los delimitadores no deben aparecer dentro del material encapsulado y no deben tener más de 70 caracteres, sin contar los dos guiones iniciales.
La línea delimitadora que sigue a la última parte del cuerpo es un delimitador distinguido que indica que no habrá más partes del cuerpo. Dicha línea delimitadora es idéntica a las líneas delimitadoras anteriores, con la adición de dos guiones más después del valor del parámetro límite.
He aquí un ejemplo que utiliza un delimitador arbitrario:
Content-Type: multipart/form-data; charset=utf-8; boundary="another cool boundary"
--another cool boundary
Content-Disposition: form-data; name="foo"
bar
--another cool boundary
Content-Disposition: form-data; name="baz"
quux
--another cool boundary--
"Extensiones de Correo de Internet Multipropósito (MIME) Segunda Parte: Tipos de Medios"
multipart/form-data contiene límite para separar los pares nombre/valor. El límite actúa como un marcador de cada trozo de pares nombre/valor que se pasa cuando se envía un formulario. El boundary se añade automáticamente a la cabecera content-type de una solicitud.
El formulario con el atributo enctype="multipart/form-data" tendrá una cabecera de petición Content-Type : multipart/form-data; boundary --- WebKit193844043-h (vaue generado por el navegador).
La carga útil pasada tiene un aspecto similar al siguiente
Content-Type: multipart/form-data; boundary=---WebKitFormBoundary7MA4YWxkTrZu0gW
-----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=”file”; filename=”captcha”
Content-Type:
-----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=”action”
submit
-----WebKitFormBoundary7MA4YWxkTrZu0gW--
En el lado del servicio web, se consume en forma @Consumes("multipart/form-data").
Tenga cuidado, cuando pruebe su webservice usando chrome postman, necesita marcar la opción de datos de formulario (botón de radio) y el menú File del cuadro desplegable para enviar el archivo adjunto. La provisión explícita del tipo de contenido como multipart/form-data arroja un error. Porque falta el boundary ya que anula la petición curl de postman al servidor con content-type añadiendo el boundary que funciona bien.