理解 HTML 表单编码:URL 编码和多部分表单
URL 编码形式
多部分表格
文本/纯文本表格
有一天,我尝试用Go编写一个 REST 端点,它将浏览器中提交的表单内容上传到另一个 REST 端点,换句话说,
Form in Browser ----> My GO Rest API ----> Another REST API
在做这些的过程中,我学到了一些HTML表单工作原理的基础知识。所以觉得分享一下我的学习成果或许是件好事,于是就写了这篇文章。:)
表单的编码类型由属性决定enctype
。它可以有三个值,
-
application/x-www-form-urlencoded
enctype
- 表示 URL 编码形式。如果属性未设置任何值,则此为默认值。 -
multipart/form-data
- 表示多部分表单。当用户想要上传文件时,会使用此类表单。 -
text/plain
- HTML5 中引入的一种新表单类型,顾名思义,它只是发送数据而不进行任何编码
现在,让我们通过示例来查看每种表单类型,以便更好地理解它们。
URL 编码形式
顾名思义,使用此类表单提交的数据是经过 URL 尾编码的。例如以下表单:
<form action="/urlencoded?firstname=sid&lastname=sloth" method="POST" enctype="application/x-www-form-urlencoded">
<input type="text" name="username" value="sidthesloth"/>
<input type="text" name="password" value="slothsecret"/>
<input type="submit" value="Submit" />
</form>
在这里,您可以看到表单使用 POST 请求提交到服务器,这意味着它有一个主体。但是主体是如何格式化的呢?它是经过 URL 编码的。基本上,它(name, value)
会创建一个长字符串,其中包含多个对。每(name, value)
对之间用一个符号分隔& (ampersand)
,并且每对(name, value)
中的 和之间也用一个符号name
分隔,例如:value
= (equals)
key1=value1&key2=value2
对于上述形式,它将是,username=sidthesloth&password=slothsecret
另外,请注意我们在操作 URL 中传递了一些查询参数/urlencoded?firstname=sid&lastname=sloth
。
URL 编码的主体和 action URL 中传递的查询参数看起来不是很相似吗?因为它们很相似。它们共享上面讨论过的格式。
尝试用上面的代码创建一个 HTML 文件,看看它在开发工具中是如何提交的。如下图所示:
这里要注意的是Content-Type
标题application/x-www-form-urlencoded
,查询字符串和表单字段以上面讨论的格式传输到服务器。
注意:不要对屏幕截图中的“表单数据”一词感到困惑。它只是 Google Chrome 表示表单字段的方式。
一切正常,但编码过程还有一些细节。让我们在提交的值中引入一些空格,例如下面的形式,它与上一个相同,但firstname
值从 更改为sid
,sid slayer
值username
也从 更改sidthesloth
为sid the sloth
。
<form action="/urlencoded?firstname=sid slayer&lastname=sloth" method="POST" enctype="application/x-www-form-urlencoded">
<input type="text" name="username" value="sid the sloth"/>
<input type="text" name="password" value="slothsecret"/>
<input type="submit" value="Submit" />
</form>
现在尝试提交表单,看看表单字段在开发工具中是如何传输的。这是 Chrome 中的开发工具 snap 代码。
显然,您可以看到空格被替换为“%20”或“+”。查询参数和表单主体均已执行此操作。
阅读此文,了解何时可以使用 + 和 %20。这涵盖了 URL 编码过程。
多部分表格
多部分表单通常用于用户需要将文件上传到服务器的情况。不过,我们只关注基于简单文本字段的表单,因为这足以理解它们的工作原理。
要将上述表单转换为多部分表单,您只需将enctype
表单标签的属性从application/x-www-form-urlencoded
更改为multipart/form-data
。
<form action="/multipart?firstname=sid slayer&lastname=sloth" method="POST" enctype="multipart/form-data">
<input type="text" name="username" value="sid the sloth"/>
<input type="text" name="password" value="slothsecret"/>
<input type="submit" value="Submit" />
</form>
让我们继续提交它并看看它在开发工具中是如何显示的。
这里有两点需要注意:Content-Type
表单请求的头部和有效载荷。让我们逐一介绍一下。
内容类型标头
标头的值Content-Type
显然是multipart/form-data
。但它还有另一个值boundary
。上例中,它的值是由浏览器生成的,但用户也可以自行定义,例如boundary=sidtheslothboundary
。下一节我们将了解它的具体用途。
请求正文
请求有效负载包含表单字段本身。每对(name, value)
字段都会被转换为以下格式的 MIME 消息部分:
--<<boundary_value>>
Content-Disposition: form-data; name="<<field_name>>"
<<field_value>>
每对都重复上述格式(name, value)
。
boundary
最后,整个有效载荷以带有 后缀的值终止--
。因此整个请求如下所示:
--<<boundary_value>>
Content-Disposition: form-data; name="<<field_name>>"
<<field_value>>
--<<boundary_value>>
Content-Disposition: form-data; name="<<field_name>>"
<<field_value>>
--<<boundary_value>>--
现在,我们看看如何使用边界值。
对于表单来说application/x-www-form-urlencoded
,&
& 符号充当每对之间的分隔符(name, value)
,使服务器能够了解参数值何时何地开始和结束。
username=sidthelsloth&password=slothsecret
对于表单来说multipart/form-data
,边界值就是用来做这个用途的。假设边界值为XXX
,请求负载应该是这样的:
--XXX
Content-Disposition: form-data; name="username"
sidthesloth
--XXX
Content-Disposition: form-data; name="password"
slothsecret
--XXX--
连字符本身不属于边界值,而是请求格式的一部分。Content-Type
上述请求的标头如下:
Content-Type: multipart/form-data; boundary=XXX
这使得浏览器能够了解每个字段何时何地开始和结束。
文本/纯文本表格
这些表单与 URL 编码表单基本相同,只是表单字段在发送到服务器时不会进行 URL 编码。它们通常使用不广泛,但它们已被引入 HTML 5 规范。
避免使用它们,因为它们是为了人类理解而不是为了机器。
正如规范中引用的那样,
使用 text/plain 格式的有效负载旨在方便人类阅读。由于格式模糊(例如,无法区分值中的文字换行符和值末尾的换行符),计算机无法可靠地解释它们。
希望我能清楚地解释我所学到的东西。下次再见,伙计们。祝你们平安。:)
在我的网站上了解有关我的更多信息..✨
文章来源:https://dev.to/sidthesloth92/understanding-html-form-encoding-url-encoded-and-multipart-forms-3lpa