很早以前,当还没有前端这个概念的时候,我在写表单提交完全不去理会表单数据的编码,在 action 属性里写好目标 URL,剩下的啊交给浏览器吧~ 但是现在,更多时候我们都采用 Ajax 方式提交数据,这种原始的方式仅仅被当成优雅降级的产物.
当我们用异步方式提交表单,就需要稍微关注一下表单数据的编码问题了.回想一下,在写回调函数时是不是有根据过请求的 Content-Type 写不同业务逻辑的经历,那这个 Content-Type 和表单的编码有什么联系吗?有没有在明明前端已经发数据给后端了,后端的小伙伴死活取不到数据的情况?这些纠结的问题背后的原因真是困扰了我好久,今天在篇文章里就要把它们掰扯清楚!
是什么决定了表单的编码?
熟悉表单元素
的小伙伴,对其中的属性 enctype 一定不会陌生,就是它规定了对表单提交给服务器时表单数据编码的内容类型 (Content Type).以下引用,摘自
html 4.01 规范的 Form 章节 :
enctype = content-type [CI]
This attribute specifies the content type used to submit the form to the server
content type?这不就是我们在回调函数里判断返回数据的类型,并且是在请求头中的那个玩意儿吗?!没错!就是它!根据 HTML 4.01 规范的基础数据类型 的说明,这个 content type 指定了连接资源的属性,同时也是 MIME type 的那些媒体类型.
表单编码类型
知道了表单编码由 enctype 决定的,那么它究竟有多少可选的取值呢?是不是所有的 MIME 类型它都能用呢?
实际上,根据 HTML5 规范 中所叙述的,enctype 具有以下三种选项,其中最后一项 text/plain 是相比 4.01 新增的.
application/x-www-form-urlencoded
multipart/form-data
text/plain
application/x-www-form-urlencoded
这是默认的编码类型,使用该类型时,会将表单数据中非字母数字的字符转换成转义字符,如 "%HH",然后组合成这种形式
key1=value1&key2=value2
;所以后端在取数据后,要进行解码.
注意:
若表单中有文件,则只留文件名;
multipart/form-data
该类型用于高效传输文件,非 ASCII 数据和二进制数据,将表单数据逐项地分成不同的部分,用指定的分割符分割每一部分.每一部分都拥有 Content-Disposition 头部,指定了该表单项的键名和一些其他信息;并且每一部分都有可选的 Content-Type,不特殊指定就为 text/plain.下面给出一个采用 multipart/form-data 编码类型的例子:
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Larry
--AaB03x
Content-Disposition: form-data; name="files"; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--AaB03x--
注意:
一般来说,method 和 enctype 是两个不同的互不影响的属性,但在传文件时,method 必须要指定为 POST,否则文件只剩下 filename 了;
当没有传文件时,enctype 会改回默认的
application/x-www-form-urlencoded
.
text/plain
按照键值对排列表单数据
key1=value1\r\nkey2=value2
,不进行转义.
注意:
若表单中有文件,则只留文件名;
application/json 及其他 MIME 类型
另外,还需要说明表单数据编码类型 application/json,已经被 W3C 遗弃(详见 HTML JSON Form Submission ),建议不要在
<form enctype="...">
中使用了,即使用了如果浏览器不支持,也会替换成
application/x-www-form-urlencoded
.
同理,其余的 MIME 类型,也不支持,均会替换成默认编码
application/x-www-form-urlencoded
.
PS:貌似现在浏览器都不支持了,我先用了下面几个浏览器:
FF43:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0) Gecko/20100101 Firefox/43.0
Chrome49, Safari9.1:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) ApplewebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36
IE6, 8
后记
所以,enctype 可以认为就是表单数据的
content type(MIME type)
,只不过其取值不能用除了上面提到的三个,否则会转换成默认的编码.
今天掰扯完了表单提交时的编码类型 enctype,以及它和 content type,MIME type 的关系.下次再总结一下 Ajax 提交表单的类型吧.
来源: http://www.bubuko.com/infodetail-2471411.html