我们在提交表单的时候,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, , beginBoundary.Length);
// 设置属性
request.Method = "POST";
request.Timeout = ;
request.ReadWriteTimeout = ;
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, , headerbytes.Length); memStream.Write(beginBoundary, , beginBoundary.Length); header = string.Format(stringKeyHeader, "AUTHMESSAGE", authJson);
headerbytes = Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, , headerbytes.Length); memStream.Write(endBoundary, , endBoundary.Length); request.ContentLength = memStream.Length;
Stream requestStream = request.GetRequestStream();
memStream.Position = ;
var tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, , tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, , 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串

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

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

    一.submit提交 在form标签中添加Action(提交的地址)和method(post),且有一个submit按钮(<input type='submit'>)就可以进行数据的提交, ...

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

    <html><head><title></title><script type="text/javascript"> f ...

  3. form 表单提交的另一种方式 js

    <html> <head> <script type="text/javascript"> function formSubmit() { fm ...

  4. js模拟form表单提交数据, js模拟a标签点击跳转,避开使用window.open引起来的浏览器阻止问题

    js模拟form表单提交数据, js模拟a标签点击跳转,避开使用window.open引起来的浏览器阻止问题 js模拟form表单提交数据源码: /** * js模拟form表单提交 * @param ...

  5. 关于AJAX与form表单提交数据的格式

    一 form表单传输文件的格式: 只有三种: multipart/form-data 一般用于传输文件,图片文件或者其他的. 那么其中我们默认的是application/x-www-form-urle ...

  6. django做form表单的数据验证

    我们之前写的代码都没有对前端input框输入的数据做验证,我们今天来看下,如果做form表单的数据的验证 在views文件做验证 首先用文字描述一下流程 1.在views文件中导入forms模块 2. ...

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

    form表单提交数据和删除文章时,TP的默认信息提示页面的看起来不是很好看,想要实现弹窗提示怎么做呢? 前端:可以使用前端的一个知识--iframe,iframe元素会创建包含另外一个文档的内联框架: ...

  8. form表单序列化数据之后,追加额外数据

    form表单序列化数据之后追加额外数据多使用在js中,下面是追加额外数据的代码: <span style="font-size:18px;">$.param({'inv ...

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

    springboot框架中集成thymeleaf引擎,使用form表单提交数据,debug结果后台获取不到数据 表单html: <form class="form-horizontal ...

随机推荐

  1. linux 配置 skywalking

    linux安装elasticsearch 一.检测是否已经安装的elasticsearch ps -aux|grep elasticsearch 二.下载elasticsearch (1)下载网站为: ...

  2. ios何时使用self.

     本文转载至  http://blog.csdn.net/lvxiangan/article/details/27204265   何时使用self.在网上搜索或者论坛里的回复大多都是简简单单的说这与 ...

  3. 使用EasyPusher进行手机低延时直播推流便捷开发

    基于EasyPusher sdk库工程(即library module)实现一个推送客户端非常简单便捷,因为sdk端已经将各种烦人的状态维护\错误检查\权限判定\UI同步等功能都实现了,开发者仅仅只需 ...

  4. 九度OJ 1079:手机键盘 (翻译)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2279 解决:1233 题目描述: 按照手机键盘输入字母的方式,计算所花费的时间 如:a,b,c都在"1"键上,输入a只 ...

  5. springmvc的过滤器和拦截器

    1 什么是过滤器 过滤器是过滤数据,比如过滤低俗文字,修改字符编码等. 2 什么是拦截器 拦截器中可以用来向ModelAndView中添加通用的数据.这样的好处是对于所有网页的公用部分就不需要在每个c ...

  6. 剑指Offer:二叉树打印成多行【23】

    剑指Offer:二叉树打印成多行[23] 题目描述 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 题目分析 Java题解 package tree; import java.uti ...

  7. 电话聊天狂人 【STL】

    7-2 电话聊天狂人(25 分) 给定大量手机用户通话记录,找出其中通话次数最多的聊天狂人. 输入格式: 输入首先给出正整数N(≤10​5​​),为通话记录条数.随后N行,每行给出一条通话记录.简单起 ...

  8. mini2440 uboot烧写uImage

    mini2440下烧写u-boot后,就可以用u-boot烧写linux内核了. 安装mkimage工具: apt-get install u-boot-tools 解压缩官方mini2440 lin ...

  9. 调用jersey发布的接口webservice,通过HttpPost传递文件

    项目媒体文件之前都是上传到七牛云处理,现在客户为了安全和私密性,准备将移动端拍摄的图片和视频传递到文件服务器,所以就想办法能不能在服务器端发布一个WebService,供移动端调用.刚好之前做的接口都 ...

  10. RQNOJ 188 购物问题:树形dp

    题目链接:https://www.rqnoj.cn/problem/188 题意: 商场以超低价格出售n个商品,购买第i个商品所节省的金额为w[i]. 为了防止亏本,有m对商品是不能同时买的.但保证商 ...