html - method - ¿Qué significa enctype=''multipart/form-data''?
multipart/form-data c# (8)
¿Qué significa enctype=''multipart/form-data''
en un formulario HTML
y cuándo debemos usarlo?
cuando deberiamos usarlo
La respuesta de Quentin es correcta: use multipart/form-data
si el formulario contiene una carga de archivo, y application/x-www-form-urlencoded
otra manera, que es la enctype
predeterminada si omite enctype
.
Voy a:
- añadir algunas referencias HTML5 más
- explique por qué tiene razón con un formulario enviar ejemplo
Referencias HTML5
Hay tres posibilidades para enctype
:
-
x-www-urlencoded
-
multipart/form-data
(puntos de especificación a RFC7578 ) -
text-plain
Esto "no se puede interpretar de manera confiable por computadora", por lo que nunca debe usarse en producción, y no lo veremos más a fondo.
Cómo generar los ejemplos.
Una vez que vea un ejemplo de cada método, se vuelve obvio cómo funcionan y cuándo debe usar cada uno.
Puedes producir ejemplos usando:
-
nc -l
o un servidor ECHO: servidor de prueba HTTP que acepta solicitudes GET / POST - un agente de usuario como un navegador o cURL
Guarde el formulario en un archivo .html
mínimo:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>upload</title>
</head>
<body>
<form action="http://localhost:8000" method="post" enctype="multipart/form-data">
<p><input type="text" name="text1" value="text default">
<p><input type="text" name="text2" value="aωb">
<p><input type="file" name="file1">
<p><input type="file" name="file2">
<p><input type="file" name="file3">
<p><button type="submit">Submit</button>
</form>
</body>
</html>
Establecemos el valor de texto predeterminado a aωb
, lo que significa aωb
porque ω
es U+03C9
, que son los bytes 61 CF 89 62
en UTF-8.
Crea archivos para subir:
echo ''Content of a.txt.'' > a.txt
echo ''<!DOCTYPE html><title>Content of a.html.</title>'' > a.html
# Binary file containing 4 bytes: ''a'', 1, 2 and ''b''.
printf ''a/xCF/x89b'' > binary
Ejecute nuestro pequeño servidor de eco:
while true; do printf '''' | nc -l 8000 localhost; done
Abra el HTML en su navegador, seleccione los archivos y haga clic en enviar y verifique el terminal.
nc
imprime la solicitud recibida.
Probado en: Ubuntu 14.04.3, nc
BSD 1.105, Firefox 40.
multipart / form-data
Firefox envió:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
Content-Length: 834
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text1"
text default
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text2"
aωb
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain
Content of a.txt.
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html
<!DOCTYPE html><title>Content of a.html.</title>
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file3"; filename="binary"
Content-Type: application/octet-stream
aωb
-----------------------------735323031399963166993862150--
Para el archivo binario y el campo de texto, los bytes 61 CF 89 62
( aωb
en UTF-8) se envían literalmente. Podrías verificar que con nc -l localhost 8000 | hd
nc -l localhost 8000 | hd
, que dice que los bytes:
61 CF 89 62
fueron enviados ( 61
== ''a'' y 62
== ''b'').
Por lo tanto está claro que:
Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266
Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266
establece el tipo de contenido enmultipart/form-data
y dice que los campos están separados por el dado cadena deboundary
.cada campo obtiene algunos subencabezados antes de sus datos:
Content-Disposition: form-data;
, elname
del campo, elfilename
delfilename
, seguido de los datos.El servidor lee los datos hasta la siguiente cadena de límite. El navegador debe elegir un límite que no aparecerá en ninguno de los campos, por lo que el límite puede variar entre solicitudes.
Debido a que tenemos un límite único, no es necesaria la codificación de los datos: los datos binarios se envían tal como están.
TODO: ¿cuál es el tamaño de límite óptimo (
log(N)
que apuesto) y el nombre / tiempo de ejecución del algoritmo que lo encuentra? Consultado en: https://cs.stackexchange.com/questions/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequencesContent-Type
es determinado automáticamente por el navegador.¿Cómo se determina exactamente cómo se preguntó? ¿Cómo se determina el tipo de mime de un archivo cargado por el navegador?
aplicación / x-www-form-urlencoded
Ahora cambie el enctype
a application/x-www-form-urlencoded
, vuelva a cargar el navegador y vuelva a enviar.
Firefox envió:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: application/x-www-form-urlencoded
Content-Length: 51
text1=text+default&text2=a%CF%89b&file1=a.txt&file2=a.html&file3=binary
Claramente, los datos del archivo no se enviaron, solo los nombres de base. Así que esto no puede ser usado para archivos.
En cuanto al campo de texto, vemos que los caracteres imprimibles habituales como a
y b
se enviaron en un byte, mientras que los no imprimibles como 0xCF
y 0x89
tomaron 3 bytes cada uno: %CF%89
!
Comparación
La carga de archivos a menudo contiene muchos caracteres no imprimibles (por ejemplo, imágenes), mientras que las formas de texto casi nunca lo hacen.
De los ejemplos hemos visto que:
multipart/form-data
: agrega unos pocos bytes de sobrecarga de límite al mensaje, y debe pasar algún tiempo en calcularlo, pero envía cada byte en un byte.application/x-www-form-urlencoded
: tiene un límite de un solo byte por campo (&
), pero agrega un factor de sobrecarga lineal de 3x por cada carácter no imprimible.
Por lo tanto, incluso si pudiéramos enviar archivos con application/x-www-form-urlencoded
, no application/x-www-form-urlencoded
hacerlo porque es muy ineficiente.
Pero para los caracteres imprimibles que se encuentran en los campos de texto, no importa y genera menos sobrecarga, por lo que simplemente lo usamos.
Al enviar un formulario, está tratando de decirle a su navegador que envíe a través del protocolo HTTP un mensaje en la red adecuadamente envuelto en una estructura de mensajes de protocolo TCP / IP. Al enviar datos, puede utilizar métodos POST
o GET
para enviar datos mediante el protocolo HTTP. POST
le dice a su navegador que cree un mensaje HTTP y ponga todo el contenido en el cuerpo del mensaje (una forma muy útil de hacer las cosas, más segura y flexible). GET
tiene algunas restricciones sobre la representación y la longitud de los datos.
Indicando lo que envias
Al enviar un archivo, es necesario informar al protocolo HTTP que está enviando un archivo que tiene varias características e información dentro de él. De esta manera, es posible enviar datos constantemente al receptor y dejar que abra el archivo con el formato actual y así sucesivamente ... Este es un requisito del protocolo HTTP como se muestra here
No puede enviar archivos usando los parámetros de enctype
predeterminados porque su receptor puede tener problemas para leerlos (considere que un archivo es un descriptor de algunos datos para un sistema operativo específico, si ve las cosas de esta manera, tal vez comprenda por qué es tan importante para especificar un enctype
diferente para los archivos).
No olvides la seguridad
Esta forma de hacer las cosas también garantiza que algunos algoritmos de seguridad funcionen en sus mensajes. Esta información también es utilizada por los enrutadores de nivel de aplicación para actuar como buenos cortafuegos para datos externos.
Bueno, como puedes ver, no es una estupidez usar un enctype
específico para archivos.
Cuando realiza una solicitud POST, tiene que codificar los datos que forman el cuerpo de la solicitud de alguna manera.
Los formularios HTML proporcionan tres métodos de codificación.
-
application/x-www-form-urlencoded
(el valor predeterminado) -
multipart/form-data
-
text/plain
Se estaba trabajando en agregar application/json
, pero se ha abandonado.
Los detalles de los formatos no son importantes para la mayoría de los desarrolladores. Los puntos importantes son:
Cuando está escribiendo el código del lado del cliente, todo lo que necesita saber es usar multipart/form-data
cuando su formulario incluya cualquier elemento <input type="file">
.
Cuando escriba el código del lado del servidor: use una biblioteca de manejo de formularios CGI->param
(por ejemplo, CGI->param
Perl o la expuesta por $_POST
superglobal de PHP) y se hará cargo de las diferencias por usted. No se moleste en tratar de analizar la entrada en bruto recibida por el servidor.
Nunca use text/plain
.
Si está escribiendo (o depurando) una biblioteca para analizar o generar los datos sin procesar, entonces debe comenzar a preocuparse por el formato. También es posible que desee saberlo por interés.
application/x-www-form-urlencoded
es más o menos lo mismo que una cadena de consulta al final de la URL.
multipart/form-data
es significativamente más complicado, pero permite que se incluyan archivos completos en los datos. Un ejemplo del resultado se puede encontrar en la especificación HTML 4 .
HTML / HTML introduce el text/plain
y es útil solo para la depuración de la especificación : no se pueden interpretar de manera confiable por computadora , y yo diría que los otros se combinaron con herramientas (como la pestaña Red en las herramientas para desarrolladores de la mayoría de los navegadores) ) son mejores para eso).
Establezca el atributo del método en POST porque el contenido del archivo no se puede colocar dentro de un parámetro de URL usando un formulario.
Establezca el valor de enctype en multipart / form-data porque los datos se dividirán en varias partes, una para cada archivo más una para el texto del cuerpo del formulario que se puede enviar con ellos.
Por lo general, esto ocurre cuando tiene un formulario POST que necesita tomar una carga de archivo como datos ... esto le dirá al servidor cómo codificará los datos transferidos, en ese caso no se codificará porque solo se transferirá y cargará Los archivos en el servidor, como por ejemplo al cargar una imagen o un pdf
enctype=''multipart/form-data''
significa que no se codificarán caracteres. es por eso que este tipo se usa al cargar archivos al servidor.
Por lo tanto, multipart/form-data
se usa cuando un formulario requiere datos binarios, como el contenido de un archivo, para ser cargados
enctype=''multipart/form-data
es un tipo de codificación que permite enviar archivos a través de un POST . Sencillamente, sin esta codificación, los archivos no se pueden enviar a través de POST .
Si desea permitir que un usuario cargue un archivo a través de un formulario, debe usar este enctype .
- El atributo enctype ( ENC ode TYPE ) especifica cómo se deben codificar los datos de formulario al enviarlos al servidor.
- multipart / form-data es uno de los valores del atributo enctype, que se usa en el elemento form que tiene una carga de archivo. multiparte significa que los datos de formulario se dividen en múltiples partes y se envían al servidor.
- Parte de la metáfora: un documento HTML tiene dos partes : una cabeza y un cuerpo.