迹忆博客
当前位置: 主页 > 学无止境 > 网络 > 文章

post Upload上传文件中multipart/form-data 做的那些事

发布时间: 2015-12-27 作者: 迹忆 浏览次数:

大家在使用form上传文件的时候都用到过 enctype=”multipart/form-data” 这个属性,那multipart/form-data 到底有什么作用呢,下面我们就来聊一聊这个话题。首先我们先看一个案例

看第一种代码

 

<form action="handle.php" method="post" >
   <input type="text" name="uname" class="uname" /><br />
   <input type="text" name="email" class="email" /><br />
   <input type="file" name="file" class="file" /><br />
   <input type="submit" name="submit" value="提交"/>
</form>

请求头信息如下

 

POST /article/handle.php HTTP/1.1
Host: www.soapstudy.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:41.0) Gecko/20100101 Firefox/41.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://www.soapstudy.com/article/postupload.html
Connection: keep-alive
Content-Length : 65
Content-Type: application/x-www-form-urlencoded

消息体:

 

uname=1234&email=12345&file=desktop.jpg&submit=%E6%8F%90%E4%BA%A4

看着眼熟,类似于 get方式传输地址栏中的 参数名1=参数值1&参数名2=参数值2 的形式。很明显,此种方式只是将文件名称通过post方式传输给服务器,仅有名称而无文件信息,这样是无法上传文件的。

接下来看第二类代码

 

<form action="handle.php" method="post" enctype="multipart/form-data">
   <input type="text" name="uname" class="uname" /><br />
   <input type="text" name="email" class="email" /><br />
   <input type="file" name="file" class="file" /><br />
   <input type="submit" name="submit" value="提交"/>
</form>

和第一段代码唯一不同的地方是form表单多了属性 enctype=”multipart/form-data” 接着在表单中输入同样的内容提交,请求信息如下

请求头信息

 

POST /article/handle.php HTTP/1.1
Host: www.soapstudy.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:41.0) Gecko/20100101 Firefox/41.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://www.soapstudy.com/article/postupload.html
Connection: keep-alive
Content-Length:529278
Content-Type:multipart/form-data;boundary=---------------------------11810260022182

(请求头信息和第一种方式不同的地方是 Content-Type, 第一种方式为application/x-www-form-urlencoded, 而此种方式为multipart/form-data; 紧跟着就是 boundary=---------------------------11810260022182——这是用来分割消息体中不同内容的,可以认为是边界,在消息体中可以看到此项应用)

消息体
(图一)

 

 

中间那乱七八糟的一大堆的东西应该就是我们的文件信息,这样服务器端收到这些信息以后,就可以将这些信息处理成相应的文件了。

通过以上案例的两种方式可以得出form表单提交数据的两种方式

1. application/x-www-form-urlencoded

2. multipart/form-data

第一种方式不能用于上传文件,只能提交文本,当然如果有file控件的话也只能提交文件名,服务器端(以PHP为例)可以通过 $_POST[]的方式接收。(可以参考 关于application/x-www-form-urlencoded 这篇文章)

第二种方式——也是我们接下来将要讨论的方式——可用于上传文件,当然服务器端处理方式不同,通过$_FILES 来接收文件信息
下面我们着重讨论multipart/form-data

(为了下文书写方便,我们将boundary=---------------------------11810260022182定义成一个变量$boundary 此变量的值为---------------------------11810260022182)

正如它的名字(form-data)所描述的一样,multipart/form-data 是用来表示表单提交的数据的,它的格式和所有的multipart MIME 数据流的格式一样。如RFC 2388描述的那样,multipart/form-data 包含很多部分,各部分之间用 --$boundary分割 其格式如下

 

--$boundary   //开始
Content-Disposition: form-data;name=”field1”
Content-Type:text/plain
Content-Transfer-Encoding:******
内容
--$boundary
Content-Disposition: form-data;name=”field2”
Content-Type:image/jpeg
内容
--$boundary-- //结束

接下来对每一项做一个大概的解释

1、--$boundary

边界是由 “--”加上$boundary(在请求头的content-type中定义的boundary=---------------------------11810260022182,见上述案例的第二种实现方式),因此消息体中的边界是比请求头中定义的多两个‘-’。对于$boundary的这个值来说,不同的应用程序(当然我们这里说的就是浏览器)产生的规则不同。

Google浏览器:

 

火狐浏览器:

 

 

但是有一点可以肯定,这个值不会和数据部分抑或是数据部分的某一段相同,当然相同的几率也是有的,不过概率非常之小,如果被我们碰上,那我们也算是相当的幸运了。

2、Content-Disposition

此项用于指定当前的呈现方式。  multipart/form-data 包含有很多部分,每一部分都包含一个Content-Disposition 头(定义在RFC 2183 )。此项的类型 为 form-data。对于name项,其值为form表单中 input的属性name的值。当然,除了类型和name这两项还可能有其它的属性,例如在案例中第二种方式的图一中可以看到第三部分还有filename项。根据传输的数据的类型的不同,Disposition 下面的内容是不同的。详细了解可以参考RFC 2183。

3、Content-Type

传输内容的类型  在multipart/form-data包含的每一项中都会有Content-Type选项,此项的默认类型为 text/plain(文本形式)。像图一中的前两部分内容是文本,因此Content-Type的类型为text/plain 由于此项为默认类型,所以有些应用程序是不显示出来的,而对于图一中的第三部分是一个图片的时候,Content-Type的类型为image/jepg。
当然此项是根据表单中的input框中的内容指定的,如果一个文件可以被作为一个正确的媒体类型,那Content-Type 的值就为此文件的类型,例如application/octet-stream、image/jpeg等。

4、Content-Transfer-encoding

当传输内容的编码方式不符合默认的编码方式的时候,此项会被用来指定相应的编码方式——可见图一中各部分数据的编码方式都符合,因此此项没有显示。

5、数据

此项就是编码以后的数据了

通过对以上几项的解释,对multipart/form-data 的格式有了一个大致的了解。当然,了解这些可能对我们当下编写只使用form表单上传文件的程序来说没有什么帮助,但是在我看来,多了解一些细节对于我们以后编写类似的程序会有很大的帮助,毕竟对于我们程序员来说要知其然,更要知其所以然。

由于本人水平有限,无法触及到更深层次的知识,本篇权当抛砖引玉,希望有高手指教,如有兴趣请在下方留言,共同讨论,共同进步

赞助
迹忆博客

上一篇:没有了

下一篇:关于application/x-www-form-urlencoded

除非注明转载,本站文章均为原创,欢迎转载,转载请以链接形式注明出处

本文地址: