HTTP协议之multipart/form-data请求分析

来源:互联网 发布:vs.php for vs2015 编辑:程序博客网 时间:2024/06/13 00:10

问题引出

在解决文件上传附带参数的时候,发现当form中添加enctype:"multipart/form-data",后台用request.getParameter(“XXX”)获取不到数据

原因分析:
1.get方式 
get方式提交的话,表单项都保存在http header中,格式是 
http://localhost:8080/hello.do?name1=value1&name2=value2这样的字符串。server端通过request.getParameter是可以取到值的。 
2.post方式(enctype为缺省的application/x-www-form-urlencoded) 
表单数据都保存在http的正文部分,格式类似于下面这样:用request.getParameter是可以取到数据的 

name1=value1&name2=value2 

3.post方式(enctype为multipart/form-data,多用于文件上传,对于只想传value的做法,显然使用application/json或者text/plain会好很多。可以把数据放到form的header或者body中,在后台使用相应的方法得到具体值) 
表单数据都保存在http的正文部分,各个表单项之间用boundary隔开。格式类似于下面这样:用request.getParameter()是取不到数据的,这时需要通过request.getInputStream来取数据,不过取到的是个InputStream,所以无法直接获取指定的表单项(需要自己对取到的流进行解析,才能得到表单项以及上传的文件内容等信息)。这种需求属于比较共通的功能,所以有很多开源的组件可以直接利用。比如:apache的fileupload组件,smartupload等。通过这些开源的upload组件提供的API,就可以直接从request中取得指定的表单项了。 

什么是multipart/form-data请求:

1、multipart/form-data的基础方法是post,也就是说是由post方法来组合实现的
2、multipart/form-data与post方法的不同之处:请求头,请求体。
3、multipart/form-data的请求头必须包含一个特殊的头信息:Content-Type,且其值也必须规定为multipart/form-data,同时还需要规定一个内容分割符用于分割请求体中的多个post的内容,如文件内容和文本内容自然需要分割开来,不然接收方就无法正常解析和还原这个文件了。具体的头信息如下:

[html] viewplain copy

1.  Content-Type: multipart/form-data; boundary=${bound}  


//其中${bound}是一个占位符,代表我们规定的分割符,可以自己任意规定,但为了避免和正常文本重复了,尽量要使用复杂一点的内容。如:--------------------56423498738365

4、multipart/form-data的请求体也是一个字符串,不过和post的请求体不同的是它的构造方式,post是简单的name=value值连接,而multipart/form-data则是添加了分隔符等内容的构造体。具体格式如下:
--${bound}  
Content-Disposition: form-data; name="Filename"  
  
HTTP.pdf  
--${bound}  
Content-Disposition: form-data; name="file000"; filename="HTTP协议详解.pdf"  
Content-Type: application/octet-stream  
  
%PDF-1.5  
file content  
%%EOF  
  
--${bound}  
Content-Disposition: form-data; name="Upload"  
  
Submit Query  
--${bound}--  
其中${bound}为之前头信息中的分割符,如果头信息中规定为123,那么这里也要为123,;可以很容易看出,这个请求体是多个相同的部分组成的:每一个部分都是以--加分隔符开始的,然后是该部分内容的描述信息,然后一个回车,然后是描述信息的具体内容;如果传送的内容是一个文件的话,那么还会包含文件名信息,以及文件内容的类型。上面的第二个小部分其实是一个文件体的结构,最后会以--分割符--结尾,表示请求体结束。

综上,可以知道要发送一个multipart/form-data的请求,其实任何支持post请求的工具或语言都可以支持,只是自己要稍微包装一下便可。

form表单设置enctype="multipart/form-data"后获取参数

方案一:js修改上传路径

 

[html] viewplain copy

1.  <form id="upload" name="upload" action="fileftp.jsp" method="post" ENCTYPE="multipart/form-data">  

2.     <input type="hidden" name="otherName" id="otherName" value="abcdefg"/>      

3.      <td nowrap>  

4.         <input type="file" id="file1" name="file1" value="" size="40" class="sbttn"/>  

5.          <input type="submit" value="上传" class="sbttn"/>  

6.     </td>   

7.  </form>  



当表单提交到fileftp.jsp后,是无法使用request.getParameter("otherName")获得到abcdefg的值的。但是可以获得到file1的文件。
这里使用JS在表单提交的时候将参数拼接在表单action地址的后面。代码像这样的:

 

[javascript] viewplain copy

1.  <script language="javascript">          

2. function formSubmit(){  

3.      var action="fileftp.jsp";         

4.     action+="?otherName="+document.upload.otherName.value;  

5.      document.upload.action=action;        

6.     document.upload.submit();  

7.  }  

8. </script> 

 

原创粉丝点击