1、HTML < form > 标签的 enctype 属性
定义和用法
enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。
默认地,表单数据会编码为 "application/x-www-form-urlencoded"。
就是说,在发送到服务器之前,所有字符都会进行编码(空格转换为 "+" 加号,特殊符号转换为 ASCII HEX 值)。
2、form表单在提交时:
1)先把form表单里的表单元素的name属性和value属性进行收集。
2)按照enctype属性的设置,选择合适的编码方式,对数据进行编码,放在请求头里
3)浏览器进行发送。
3、application/x-www-form-urlencoded
这应该是最常见的 POST 提交数据的方式了。
浏览器的原生 < form > 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。
此时可以看到:
Content-Type: application/x-www-form-urlencoded;charset=utf-8
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
首先,Content-Type 被指定为 application/x-www-form-urlencoded;
其次,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。
大部分服务端语言都对这种方式很好的支持,常用的如jQuery中的ajax请求,Content-Type 默认值都是application/x-www-form-urlencoded;charset=utf-8
1)它是post的默认格式,使用js中URLencode转码方法。
包括将name、value中的空格替换为加号;将非ascii字符做百分号编码;将input的name、value用‘=’连接,不同的input之间用‘&’连接。
2)百分号编码什么意思呢。
比如汉字‘丁’吧,他的utf8编码在十六进制下是0xE4B881,占3个字节,把它转成字符串‘E4B881’,变成了六个字节,每两个字节前加上百分号前缀,得到字符串“%E4%B8%81”,变成九个ascii字符,占九个字节(十六进制下是0x244534254238253831)。
把这九个字节拼接到数据包里,这样就可以传输“非ascii字符的 utf8编码的 十六进制表示的 字符串的 百分号形式”,^_^。
3)同样使用URLencode转码,这种post格式跟get的区别在于,get把转换、拼接完的字符串用‘?’直接与表单的action连接作为URL使用,所以请求体里没有数据;
而post把转换、拼接后的字符串放在了请求体里,不会在浏览器的地址栏显示,因而更安全一些。
4、multipart/form-data
这也是常见的post请求方式,一般用来上传文件,各大服务器的支持也比较好。
所以我们使用表单 上传文件 时,必须让
通过 form 表单提交文件操作如下:
浏览器将会发送以下数据:
POST /t2/upload.do HTTP/1.1
User-Agent: SOHUWapRebot
Accept-Language: zh-cn,zh;q=0.5
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Content-Length: 60408
Content-Type:multipart/form-data; boundary=ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
Host: w.sohu.com
--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
Content-Disposition: form-data; name="city"
Santa colo
--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
Content-Disposition: form-data;name="desc"
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
...
--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
Content-Disposition: form-data;name="pic"; filename="photo.jpg"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
... binary data of the jpg ...
--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC--
从上面的 multipart/form-data 格式发送的请求的样式来看,
它包含了多个 Parts,每个 Part 都包含头信息部分,Part 头信息中必须包含一个 Content-Disposition 头,
其他的头信息则为可选项, 比如 Content-Type 等。
Content-Disposition 包含了 type 和 一个名字为 name 的 parameter,
type 是 form-data,name 参数的值则为表单控件(也即 field)的名字,
如果是文件,那么还有一个 filename 参数,值就是文件名。
比如:
Content-Disposition: form-data; name="user"; filename="hello.txt"
上面的 “user” 就是表单中的控件的名字,后面的参数 filename 则是点选的文件名。对于可选的 Content-Type(如果没有的话),默认就是 text/plain。
注意:
如果文件内容是通过填充表单来获得,
那么上传的时候,Content-Type 会被自动设置(识别)成相应的格式,
如果没法识别,那么就会被设置成 “application/octet-stream”
如果多个文件被填充成单个表单项,那么它们的请求格式则会是 multipart/mixed。
如果 Part 的内容跟默认的 encoding 方式不同,那么会有一个 "content-transfer-encoding" 头信息来指定。
下面,我们填充两个文件到一个表单项中,行程的请求信息如下:
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Larry
--AaB03x
Content-Disposition: form-data; name="files"
Content-Type: multipart/mixed; boundary=BbC04y
--BbC04y
Content-Disposition: file; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--BbC04y
Content-Disposition: file; filename="file2.gif"
Content-Type: image/gif
Content-Transfer-Encoding: binary
...contents of file2.gif...
--BbC04y--
--AaB03x--