浏览器原生 form 表单POST 数据的两种方式

我们在提交表单的时候,form表单参数中会有一个enctype的参数。enctype指定了HTTP请求的Content-Type。

常用有两种:application/x-www-form-urlencoded和multipart/form-data。

application/x-www-form-urlencoded: 窗体数据被编码为名称/值对,并且将提交的数据进行urlencode默认情况下,我们所有的表单提交都是通过这种默认的方式实现的。

multipart/form-data: 窗体数据被编码为一条消息,页上的每个控件对应消息中的一个部分

当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1&name2=value2...),然后把这个字串append到url后面,用?分割,加载这个新的url。

当action为post时候,浏览器把form数据封装到http body中,然后发送到server。 如果没有type=file的控件,用默认的application/x-www-form-urlencoded就可以了。

请求标头: 

请求正文:

loginType=1&loginName=operator&pwd=%E1%8D%B0%E1%8D%B0%E1%8D%B0%E1%8D%B0%E1%8D%B0%E1%8D%B0&verifyCode=6987

首先,Content-Type 被指定为 application/x-www-form-urlencoded;其次,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。大部分服务端语言都对这种方式有很好的支持。

但是如果有type=file的话,就要用到multipart/form-data了。浏览器会把整个表单以控件为单位分割,并为每个部分加上Content-Disposition(form-data或者file),Content-Type(默认为text/plain),name(控件name)等信息,并加上分割符(boundary)。

Multipart/form-data其实就是浏览器用表单上传文件的方式。最常见的情境是:在写邮件时,向邮件后添加附件,附件通常使用表单添加,也就是用multipart/form-data格式上传到服务器。

具体的步骤是怎样的呢?

首先,客户端和服务器建立连接(TCP协议)。

第二,客户端可以向服务器端发送数据。因为上传文件实质上也是向服务器端发送请求。

第三,客户端按照符合“multipart/form-data”的格式向服务器端发送数据。

服务端接收的http请求标头:

请求正文:

-----------------------------7e11a616672236
Content-Disposition: form-data; name="id"

17e832d6a79744eaae6d79237e82e3a4

-----------------------------7e11a616672236
Content-Disposition: form-data; name="templateType"

1
-----------------------------7e11a616672236
Content-Disposition: form-data; name="file"; filename=""
Content-Type: application/octet-stream

<二进制文件数据未显示>
---------------------------7e11a616672236
Content-Disposition: form-data; name="imagesTemplate"

-----------------------------7e11a616672236
Content-Disposition: form-data; name="attachTemplate"

-----------------------------7e11a616672236
Content-Disposition: form-data; name="ajax"

1
-----------------------------7e11a616672236--

这行指出这个请求是“multipart/form-data”格式的,且“boundary”是 “---------------------------7e11a616672236”这个字符串。

不难想象,“boundary”是用来隔开表单中不同部分数据的。例子中的表单就有 6 部分数据,用“boundary”隔开。“boundary”一般由系统随机产生,但也可以简单的用“-------------”来代替。

实际上,每部分数据的开头都是由"--" + boundary开始,而不是由 boundary 开始。仔细看才能发现下面的开头这段字符串实际上要比 boundary 多了个 “--”

紧接着 boundary 的是该部分数据的描述。

在请求的最后,则是 "--" + boundary + "--" 表明表单的结束

需要注意的是,在html协议中,用 “/r/n” 换行,而不是 “/n”

附C#组装代码:

var memStream = new MemoryStream();
                //https支持
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(httpUrl);
                // 边界符
                var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
                // 边界符
                var beginBoundary = Encoding.ASCII.GetBytes("--" + boundary + "\r\n");
                // 最后的结束符
                var endBoundary = Encoding.ASCII.GetBytes("--" + boundary + "--\r\n");
                memStream.Write(beginBoundary, 0, beginBoundary.Length);
                // 设置属性
                request.Method = "POST";
                request.Timeout = 50000000;
                request.ReadWriteTimeout = 30000000;
                request.ContentType = "multipart/form-data; boundary=" + boundary;

                var stringKeyHeader = "Content-Disposition: form-data; name=\"{0}\"" +
                                      "\r\n\r\n{1}\r\n";
                var header = string.Format(stringKeyHeader, "REQMESSAGE", bodyJson);
                var headerbytes = Encoding.UTF8.GetBytes(header);
                memStream.Write(headerbytes, 0, headerbytes.Length);

                memStream.Write(beginBoundary, 0, beginBoundary.Length);

                header = string.Format(stringKeyHeader, "AUTHMESSAGE", authJson);
                headerbytes = Encoding.UTF8.GetBytes(header);
                memStream.Write(headerbytes, 0, headerbytes.Length);

                memStream.Write(endBoundary, 0, endBoundary.Length);

                request.ContentLength = memStream.Length;
                Stream requestStream = request.GetRequestStream();
                memStream.Position = 0;
                var tempBuffer = new byte[memStream.Length];
                memStream.Read(tempBuffer, 0, tempBuffer.Length);
                memStream.Close();
                requestStream.Write(tempBuffer, 0, tempBuffer.Length);
                requestStream.Close();
    /*string s = System.Text.Encoding.UTF8.GetString(tempBuffer, 0, tempBuffer.Length);
    Console.WriteLine(s);*/
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("UTF-8"));//("gb2312"));
                resultInfo = sr.ReadToEnd();

实现的是传递两个json串

时间: 2024-10-12 18:25:17

浏览器原生 form 表单POST 数据的两种方式的相关文章

Form表单提交数据的几种方式

一.submit提交 在form标签中添加Action(提交的地址)和method(post),且有一个submit按钮(<input type='submit'>)就可以进行数据的提交,每一个input标签都需要有一个name属性,才能进行提交. <form action='http://www.123.com/postValue' method='post'> <input type='text' name='username' /> <input type=

springMVC接受ajax提交表单,json数据的两种方式

作为一个初入互联网行业的小鑫鑫,在使用springMVC时发现一个好耍的东西,决定记下来,免得哪天忘了,哈哈 第一种 序列化表单,将表单数据序列化为json对象字符串 $("#submit").click(function (){ var form=$("form").serializeArray(); $.ajax({ url:"${pageContext.request.contextPath}/teacher/updateTeacher",

获取form表单元素值的4种方式

<html><head><title></title><script type="text/javascript"> function checkForm(){ var name=document.form1.number.value; //or form1.number.value var name=document.forms[0].number.value; var name=document.forms[0]['num

HTML5第8次课堂笔记( 模拟form表单提交数据,xml的解析,jQuery的Ajax方法使用, mui的ajax)

HTML5第8次课堂笔记 1.  模拟form表单提交数据:(get方式) <body> <formmethod="get"action="DataTest7"> <inputtype="text"name="uname"value="yang"id="myname"><br/> <inputtype="password&q

ubuntu 下CGI c语言 获取form表单的数据

前面文章:使用cgi c 写了一个helloworld 这次 主要使用CGI c语言 获取form表单的数据 1 login.c [email protected]:/usr/lib/cgi-bin$ cat login.c #include<stdio.h> #include<stdlib.h> #include <string.h> int main(){ int i,len=0; char poststr[100]; char m[10],n[10]; char

FormData实现form表单的数据打包

FormData实现form表单的数据打包 2015-02-04 HTML代码: <html> ????<head> ????<title>FormData</title>? ????<script?type="text/javascript"> /*formData?表单数据 ?这是在html5中新增的一个API ?能以表单对象作为参数,自动的把表单的数据打包 ?当ajax发送数据时,发送些formData, ?达到发送表单

thinkPHP5.0使用form表单提交数据和删除文章,不用TP的提示页面,使用弹出提示信息

form表单提交数据和删除文章时,TP的默认信息提示页面的看起来不是很好看,想要实现弹窗提示怎么做呢? 前端:可以使用前端的一个知识--iframe,iframe元素会创建包含另外一个文档的内联框架:target,规定在何处打开链接文档. 另外想要实现一个好看的方便.能重复使用的弹窗就要开发一个弹窗插件了,这里推荐使用前端的弹窗插件sweetalert.js,为了方便.重复使用我们把它成封装一个函数,页面要引入sweetalert.js的css和js文件 后端:为了方便以后重复使用,先写一个公共

springboot框架中集成thymeleaf引擎,使用form表单提交数据,debug结果后台获取不到数据

springboot框架中集成thymeleaf引擎,使用form表单提交数据,debug结果后台获取不到数据 表单html: <form class="form-horizontal form-material" th:object="${user}" th:action="@{/user/updateOneUserInfo}" method="post"> <input type="hidden

关于Mysql删除表数据的两种方式对比

1.delete from table_name 一行一行删除,只删除表数据,auto_increament仍停留在最后一天数据的下一个值. 2.truncate table_name 快捷删除表数据.先删除整个表,然后重新建表结构.auto_increament从1开始. 关于Mysql删除表数据的两种方式对比,布布扣,bubuko.com