简单的HTTP POST

大家通过HTTP向服务器发送POST请求提交数据,都是通过form表单提交的,代码如下:

<form method="post"action="http://w.sohu.com" >

<inputtype="text" name="txt1">

<inputtype="text" name="txt2">

</form>

提交时会向服务器端发出这样的数据(已经去除部分不相关的头信息),数据如下:

POST / HTTP/1.1

Content-Type:application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

Host: w.sohu.com

Content-Length: 21

Connection: Keep-Alive

Cache-Control: no-cache

txt1=hello&txt2=world

对于普通的HTML Form POST请求,它会在头信息里使用Content-Length注明内容长度。头信息每行一条,空行之后便是Body,即“内容”(entity)。它的Content-Type是application/x-www-form-urlencoded,这意味着消息内容会经过URL编码,就像在GET请 求时URL里的QueryString那样。txt1=hello&txt2=world

POST上传文件

最早的HTTP POST是不支持文件上传的,给编程开发带来很多问题。但是在1995年,ietf出台了rfc1867,也就是《RFC 1867 -Form-based File Upload in HTML》,用以支持文件上传。所以Content-Type的类型扩充了multipart/form-data用以支持向服务器发送二进制数据。因此发送post请求时候,表单<form>属性enctype共有二个值可选,这个属性管理的是表单的MIME编码:

①application/x-www-form-urlencoded(默认值)
 ②multipart/form-data
其实form表单在你不写enctype属性时,也默认为其添加了enctype属性值,默认值是enctype="application/x- www-form-urlencoded".

通过form表单提交文件操作如下:                                                      设置编码方式(enctype)为multipart/form-data

<form method="post"action="http://w.sohu.com/t2/upload.do" enctype=”multipart/form-data”>

<inputtype="text" name="desc">

<inputtype="file" name="pic">

</form>

浏览器将会发送以下数据:

POST /t2/upload.do HTTP/1.1

User-Agent: SOHUWapRebot

Accept-Language: zh-cn,zh;q=0.5

Accept-Charset: GBK,utf-8;q=0.7,*;q=0.7

Connection: keep-alive

Content-Length: 60408

Content-Type:multipart/form-data; boundary=ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC

Host: w.sohu.com

--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC

Content-Disposition: form-data;name="desc"

Content-Type: text/plain; charset=UTF-8

Content-Transfer-Encoding: 8bit

[......][......][......][......]...........................

--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC

Content-Disposition: form-data;name="pic"; filename="photo.jpg"

Content-Type: application/octet-stream

Content-Transfer-Encoding: binary

[图片二进制数据]

--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC--

我们来分析下数据,第一个空行之前自然还是HTTP header,之后则是Entity,而此时的Entity也比之前要复杂一些。根据RFC 1867定义,我们需要选择一段数据作为“分割边界”( boundary属性),
这个“边界数据”不能在内容其他地方出现,一般来说使用一段从概率上说“几乎不可能”的数据即可。
不同浏览器的实现不同,例如火狐某次post的  boundary=---------------------------32404670520626 , opera为boundary=----------E4SgDZXhJMgNE8jpwNdOAX ,
每次post浏览器都会生成一个随机的30-40位长度的随机字符串,浏览器一般不会遍历这次post的所有数据找到一个不可能出现在数据中的字符串,这样代价太大了。
一般都是随机生成,如果你遇见boundary值和post的内容一样,那样的话这次上传肯定失败,不过我建议你去买彩票,你太幸运了。Rfc1867这样说明{A boundary is selected that does not occur in any of the data. (This selection is sometimes done probabilisticly.)}。

选择了这个边界之后,浏览器便把它放在Content-Type 里面传递给服务器,服务器根据此边界解析数据。下面的数据便根据boundary划分段,每一段便是一项数据。(每个field被分成小部分,而且包含一个value是"form-data"的"Content-Disposition"的头部;一个"name"属性对应field的ID,等等,文件的话包括一个filename)

  • IE和Chrome在filename的选择策略上有所不同,前者是文件的完整路径,而后者则仅仅是文件名。
  • 数据内容以两条横线结尾,并同样以一个换行结束。在网络协议中一般都以连续的CR、LF(即\r、\n,或0x0D、Ox0A)字符作为换行,这与Windows的标准一致。如果您使用其他操作系统,则需要考虑它们的换行符

另外Content-length 指的是所用数据的长度。

参考:

Rfc1867:http://www.ietf.org/rfc/rfc1867

Rfc1867:http://www.vivtek.com/rfc1867.html

Multipart/form-data POST文件上传的更多相关文章

  1. Ajax(form表单文件上传、请求头之contentType、Ajax传递json数据、Ajax文件上传)

    form表单文件上传 上菜 file_put.html <form action="" method="post" enctype="multi ...

  2. jquery.form 兼容IE89文件上传

    导入部分 <script type="text/javascript" src="js/jquery-1.8.3.min.js" charset=&quo ...

  3. Django 基于Ajax & form 简单实现文件上传

    前端实现 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="U ...

  4. form表单文件上传提交且接口回调显示提交成功

    前端: <form method="post" enctype="multipart/form-data" id="formSubmit&quo ...

  5. form表单文件上传 servlet文件接收

    需要导入jar包 commons-fileupload-1.3.2.jar commons-io-2.5.jar Upload.Jsp代码 <%@ page language="jav ...

  6. Spring MVC-表单(Form)标签-文件上传(File Upload)示例(转载实践)

    以下内容翻译自:https://www.tutorialspoint.com/springmvc/springmvc_upload.htm 说明:示例基于Spring MVC 4.1.6. 以下示例显 ...

  7. 实用ExtJS教程100例-009:ExtJS Form无刷新文件上传

    文件上传在Web程序开发中必不可少,ExtJS Form中有一个filefield字段,用来选择文件并上传.今天我们来演示一下如何通过filefield实现ExtJS Form无刷新的文件上传. 首先 ...

  8. WebApi实现Ajax模拟Multipart/form-data方式多文件上传

    前端页面代码: <input type="file" class="file_control" /><br /> <input t ...

  9. SSM+form表单文件上传

    这里介绍SSM如何配置上传文件 配置springmvc.xml: <!--配置上传下载--> <bean id="multipartResolver" class ...

  10. multipart/form-data请求与文件上传的细节

    <!DOCTYPE html><html><head lang="en">  <meta charset="UTF-8" ...

随机推荐

  1. Python3:numpy模块中的argsort()函数

    Python3:numpy模块中的argsort()函数   argsort函数是Numpy模块中的函数: >>> import numpy >>> help(nu ...

  2. 刽子手游戏(Hangman Judge, UVa 489)

    刽子手游戏其实是一款猜单词游戏,游戏规则是这样的:计算机想一个单词让你猜,你每次可以猜一个字母.如果单词里有那个字母,所有该字母会显示出来:如果没有那个字母,则计算机会在一幅“刽子手”画上填一笔.这幅 ...

  3. web前端学习总结--JQuery

    jQuery 什么是jQuery jQuery是一个优秀的JavaScript框架,一个轻量级的JS库. 它封装了JS.CSS.DOM,提供了一致的.简洁的API. 兼容CSS3,及各种浏览器 使用户 ...

  4. SprinMVC接收参数乱码解决篇

    1.Spring 默认的字符编码格式为iso-8859-1,为此Spring专门提供了字符过滤器org.springframework.web.filter.CharacterEncodingFilt ...

  5. Flask - 安装,仪式, 返回, 和 请求

    目录 Flask - 第一篇 安装,仪式, 返回, 和 请求 一. Flask 的安装 和 程序员仪式 安装 程序员仪式 二. Flask 的返回值 三. Flask 请求request Flask ...

  6. PAT 1034. Head of a Gang

    1034. Head of a Gang (30) One way that the police finds the head of a gang is to check people's phon ...

  7. vim学习3-查找替换

    一.字符的替换及撤销(Undo操作) 1.替换和撤销(Undo)命令 替换和Undo命令都是针对普通模式下的操作 命令 说明 r+<待替换字母> 将游标所在字母替换为指定字母 R 连续替换 ...

  8. 【无限滚动加载数据】—infinite-scroll插件的使用

    网上对于infinite-scroll插件使用的例子不多.但由于它的出现,鼓吹了瀑布流形式的页面展示方式,所以不得不了解了解这种新的分页方式. 官网上有对infinite-scroll的详细描述,但一 ...

  9. Nginx不转发http header

    使用nginx做http代理时,在Header中使用了一个名为api_key的属性,碰到http header不转发的问题. 问题源码: rc = ngx_http_parse_header_line ...

  10. hdu_1056_HangOver_201311071354

    HangOver Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...