在学习如何从POST请求中获取表单数据之前,让我们先来了解一下HTML表单。在绝大多数情况下,POST请求都是通过HTML表单发送的,这些表单看上去通常会是下面这个样子:

<form action="/process" method="post">
  <input type="text" name="first_name"/>
  <input type="text" name="last_name"/>
  <input type="submit"/>
</form>

<form>标签可以包围文本行、文本框、单选按钮、复选框以及文件上传等多种HTML表单元素,而用户则可以把想要传递给服务器的数据输入到这些元素里面。当用户按下发送按钮、又或者通过某种方式触发了表单的发送操作之后,用户在表单中输入的数据就会被发送至服务器。

用户在表单中输入的数据会以键值对的形式记录在请求的主体中,然后以HTTP POST请求的形式发送至服务器。因为服务器在接收到浏览器发送的表单数据之后,还需要对这些数据进行语法分析,从而提取出数据中记录的键值对,因此我们还需要知道这些键值对在请求主体中是如何格式化的。

HTML表单的内容类型(content type)决定了POST请求在发送键值对时将使用何种格式,其中,HTML表单的内容类型是由表单的enctype属性指定的:

<form action="/process" method="post" enctype="application/x-www-form-urlencoded">
  <input type="text" name="first_name"/>
  <input type="text" name="last_name"/>
  <input type="submit"/>
</form>

enctype属性的默认值为application/x-www-form-urlencoded。浏览器至少需要支持application/x-www-form-urlencodedmultipart/form-data这两种编码方式。除以上两种编码方式之外,HTML5还支持text/plain编码方式。

如果我们把enctype属性的值设置为application/x-www-form-urlencoded,那么浏览器将把HTML表单中的数据编码为一个连续的“长查询字符串”(long query string):在这个字符串中,不同的键值对将使用&符号分隔,而键值对中的键和值则使用等号=分隔。

这种编码方式跟我们在第1章看到过的URL编码是一样的,application/x-www-form-urlencoded编码名字中的urlencoded一词也由此而来。换句话说,一个application/x-www- form-urlencoded编码的HTTP请求主体看上去将会是下面这个样子的:

first_name=sau%20sheong&last_name=chang

但是,如果我们把enctype属性的值设置为multipart/form-data,那么表单中的数据将被转换成一条MIME报文:表单中的每个键值对都构成了这条报文的一部分,并且每个键值对都带有它们各自的内容类型以及内容配置(disposition)。以下是一个使用multipart/form-data编码对表单数据进行格式化的例子:

------WebKitFormBoundaryMPNjKpeO9cLiocMw
Content-Disposition: form-data; name="first_name"

sau sheong 
------WebKitFormBoundaryMPNjKpeO9cLiocMw 
Content-Disposition: form-data; name="last_name" 

chang 
------WebKitFormBoundaryMPNjKpeO9cLiocMw--

既然表单同时支持application/x-www-form-urlencoded编码和multipart/form-data编码,那么我们该选择使用哪种编码呢?答案是,如果表单传送的是简单的文本数据,那么使用URL编码格式更好,因为这种编码更为简单、高效,并且它所需的计算量要比另一种编码少。但是,如果表单需要传送大量数据(如上传文件)那么使用multipart/form- data编码格式会更好一些。在需要的情况下,用户还可以通过Base64编码,以文本方式传送二进制数据。

到目前为止,我们只讨论了如何通过POST请求发送表单,但实际上通过GET请求也是可以发送表单的——因为HTML表单的method属性的值既可以是POST也可以是GET,所以下面这个HTML表单也是合法的:

<form action="/process" method="get">  
    <input type="text" name="first_name"/>  
    <input type="text" name="last_name"/>
    <input type="submit"/>
</form>

因为GET请求并不包含请求主体,所以在使用GET方法传递表单时,表单数据将以键值对的形式包含在请求的URL里面,而不是通过主体传递。

在了解了HTML表单向服务器传递数据的方法之后,让我们回到服务器一端,学习一下如何使用net/http库来处理这些表单数据。

results matching ""

    No results matching ""