在web开发中最常见的莫过于GET和POST,其中GET一般将参数编码在url中(HTTP header)来传递数据; 而POST或PUT数据必须放在消息主体(entity-body)中,这样的数据便是HTTP表单,表单数据的编码方式应在HTTP头中进行设置(Content-Type header字段),常见的编码方式有(HTTP采用MIME框架,编码方式可以是任何MIME类型):

  1. URLencoded: application/x-www-form-urlencoded
  2. Multipart: multipart/form-data
  3. JSON: application/json
  4. XML: text/xml
  5. 纯文本: text/plain

在Web开发中,前三种格式非常常见。HTML中<form>支持urlencoded,multipart,plain text,通过enctype属性来进行设置。AJAX中默认的则是JSON编码格式。

URLencoded

HTML中<form>标签的enctype属性用来指定表单编码格式,默认为application/x-www-form-urlencoded,即以下两个表单完全等价。

<form method='post'>
  <input type="text" name='title'>
  <input type="text" name='subtitle'>
  <input type="submit">
</form>
<form  method='post' enctype='application/x-www-form-urlencoded'>
  <input type="text" name='title'>
  <input type="text" name='subtitle'>
  <input type="submit">
</form>

上述表单将会显示为两个文本框和一个提交按钮。我们在文本框中分别写入test中国后,点击提交按钮。产生的HTTP请求可能是这样的:

可以打开Chrome控制台的Network标签,找到这次请求,便可以看到下面的信息。

请求头(这里只给出了Content-Type字段):

POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded

请求体:

title=test&subtitle=%E4%B8%AD%E5%9B%BD

这里你看到的%E4%B8%AD%E5%9B%BD即是中国按照base64编码(url通用的编码方式)后的结果。可以在Chrome Console中通过decodeURI('%E4%B8%AD%E5%9B%BD')来解码。

Multipart

multipart编码方式则需要设置enctypemultipart/form-data

<form method="post" enctype="multipart/form-data">
    <input type="text" name="title" value="harttle">
    <input type="file" name="avatar">
    <input type="submit">
</form>

这里我们还设置了<input type='text'>的默认值为harttle

该表单将会显示为一个文本框、一个文件按钮、一个提交按钮。然后我们选择一个文件:chrome.png,点击表单提交后产生的请求可能是这样的:

请求头:

POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA

请求体:

------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="title"

harttle
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="avatar"; filename="chrome.png"
Content-Type: image/png

 ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

这便是一个multipart编码的表单。Content-Type中还包含了boundary的定义,它用来分隔请求体中的每个字段。正是这一机制,使得请求体中可以包含二进制文件(当然文件中不能包含boundary)。

除了application/x-www-form-urlencodedmultipart/form-data,HTML的<form>还支持text/plain。此外,如果想提交其他编码类型的表单,必须通过AJAX技术,接下来我们介绍一个常用的JSON数据的提交。

JSON

从JavaScript中提交JSON数据真是再方便不过了,jquery、angularJS等框架都封装了更好用的AJAX方法。例如:

$.post('/xxx', {
        title: 'test',
        content: [1,2,3]
    });

该JavaScript执行后可能生成如下的HTTP请求:

请求头:

POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8

请求体:

{"title":"test","content":[1,2,3]}

XML

请求头:

POST http://www.example.com HTTP/1.1
Content-Type: text/xml

请求体:

<!--?xml version="1.0"?-->
<methodcall>
    <methodname>examples.getStateName</methodname>
    <params>
        <param>
            <value><i4>41</i4></value>
    </params>
</methodcall>

本文采用 知识共享署名 4.0 国际许可协议(CC-BY 4.0)进行许可,转载注明来源即可: https://harttle.land/2016/04/11/http-form-encoding.html。如有疏漏、谬误、侵权请通过评论或 邮件 指出。