还是一个异常引发的故事:
需要实现一个手机客户端行为分析的需求,手机客户端需要上传一些数据文件。手机客户端通过http协议post方式上传数据文件的时候,我们发现在服务器端无法通过request.getInputStream()获取到相应的数据,调用request.getInputStream()读取数据里头啥都木有。
经过各种尝试我们注意到如下的情况:
1.在不做任何修改的情况下,调用request.getParameter()可以获取到部分数据,即url拼接参数的数据。
2.在不做任何修改的情况下,如果在之前任何地方都不调用request.getParameter(),而是直接调用request.getInputStream()是可以获取到数据的。
3.原来客户端使用默认的请求头Content-Type:application/x-www-form-urlencoded,修改此值为multipart/form-data或者application/octet-stream之后,通过request.getInputStream()可以获取到数据,即使之前调用过request.getParameter()。
最后的解决方法当然是客户端修改Content-Type,因为服务器端request.getInputStream()的方法不方便修改。今天具体分析下里头的原理。
一.从form的enctype属性到Content-Type
写html的时候我们都知道form有个属性enctype,默认值是application/x-www-form-urlencoded,这个值表示会将表单数据用&符号做一个简单的拼接。例如:
我们注意到这个时候Content-Type为application/x-www-form-urlencoded。
如果enctype的值为multipart/form-data,这个值一般用于表单中包含文件上传的情况,它会将表单中的数据使用一个boundary作为分隔上传。例如:
我们注意到这个时候Content-Type也相应的变为multipart/form-data,同时后面还加上了分隔符boundary的描述。
所以,其实form的enctype属性某种程度上决定了Content-Type值和请求body里头的数据格式。
详细的可以参考:http://imzc.net/archives/131
二.从Content-Type到request.getInputStream()
上面说到了form的处理情况,但是其实如果我们不是使用浏览器,而是自己实现的客户端来传递数据的话,这些头信息就得都由自己处理。
所以上面就出现了,上传文件的时候仍然使用了application/x-www-form-urlencoded的不标准用法。
但是为啥Content-Type会影响request的处理呢?这得从request的一些实现说起。
request.getParameter()、 request.getInputStream()、request.getReader()这三种方法是有冲突的,因为流只能被读一次。
比如:当form表单内容采用 enctype=application/x-www-form-urlencoded编码时,先通过调用request.getParameter() 方法得到参数后,再调用 request.getInputStream()或request.getReader()已经得不到流中的内容,因为在调用 request.getParameter()时系统可能对表单中提交的数 据以流的形式读了一次,反之亦然。
当form表单内容采用 enctype=multipart/form-data编码时,即使先调用request.getParameter()也得不到数据,但是这时调用 request.getParameter()方法对 request.getInputStream()或request.getReader()没有冲突,即使已经调用了 request.getParameter()方法也 可以通过调用request.getInputStream()或request.getReader()得 到表单中的数据,而request.getInputStream()和request.getReader()在同
一个响应中是不能混合使用的,如果混合使用就会抛异常。
更多也可以参考:http://robert-liu.iteye.com/blog/713568
分享到:
相关推荐
解决当FORM的ENCTYPE="multipart/form-data" 时request.getParameter()获取不到值的方法 ?
四种常见的 POST 提交数据方式对应的content-type取值(enctype)
解决上传文件enctype= multipart/form-data 时无法传递其他参数的问题,以及项目全局编码问题。用的插件是commons io + commons fileupload
解决当FORM的ENCTYPE="multipart/form-data" 时action方法或者控制层用request.getParameter()获取不到值的方法 ?
解决java enctype multipart form-data文件上传传值问题 不使用jspsmartupload组件 可以轻轻松松 解决传值问题
encType="multipart/form-data" 根据上传不同,主要分两步,可以有效的解决request.getParameter(String s)是null值
//注意action地址,还有enctype要写成multipart/form-data,和method="POST" <form name="uploadform" method="POST" action="./servlet/FileUpload" ENCTYPE="multipart/form-data"> <tr><td width="100%" ...
我们都知道要让form能提交文件,需要在form上指定enctype=multipart/form-data的attribute,这样才能上传文件,关于enctype的文章很多,就不再做解释。 问题是因为使用了MVC的Html.BeginForm()来输出表单代码,默认...
ssid=xiaomi&encryption=NONE&enctype=NONE&channel=1%3B%2Fusr%2Fsbin%2Ftelnetd,然后查看返回的JSON数据{"msg":"未能连接到指定WiFi(Probe timeout)","code":1616},返回码有可能不同,但是这里已经可以通过...
servlet上传 enctype="multipart/form-data" servlet上传 enctype="multipart/form-data
commons-lang-2.3.jar,在使用组件实现文件上传时候要注意前后台的一致性,注意在后台定义File文件对象名要与jsp页面中的file标签name名字一致,前台form标签属性一定要设置为enctype="multipart/form-data",而且...
// headers:{"ClientCallMode" : "ajax"},//添加请求头部 enctype="multipart/form-data" success: function(data){ if(data.msg=="success"){ alert("保存成功"); }else{ alert("保存失败")...
enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。 值 描述 application/x-www-form-urlencoded 在发送前编码所有字符(默认) multipart/form-data 不对字符编码。在使用包含文件上传控件...
在文件上载和表单提交的过程中,有两个指的关心的问题,一是上载的数据是是采用的那种方式的编码,这个问题的可以从 Content-Type 中得到答案,另一个是问题是上载的数据量有多少即 Content-Length ,知道了它,就...
Enctype :指定将数据回发到服务器时浏览器使用的编码类型。用于表单里有图片上传。 编码类型有以下三种: application/x-www-form-urlencoded: 在发送前编码所有字符(默认)。这是标准的编码格式。 multipart/...
使用中需要注意的问题: 1,不能直接使用Request.form()方法,否则报错 请求对象 错误 'ASP 0206 : 80004005' 这是因为上传类调用的BinaryRead方法...2,使用上传类时form标签必须添加属性 enctype="multipart/form-data
另外,还需要增加上传的属性enctype= “multipart/form-data”,该属性说明浏览器可以提供文件上传功能。 2.编写处理表单提交的PHP脚本 当用户通过上传表单选择一个文件并提交后,PHP会自动生成一个$_FILES的二维...
out.print("the enctype must be multipart/form-data"); } %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=GB18030"> <title>File upload</title&...
content=request.form(\"content\") set rs=server.createobject(\"adodb.recordset\") sql=\"select * from biao\" rs.open sql,conn,3,2 rs.addnew rs(\"name\")=name if content<>\"\" then rs(\"content\...
用 Enctype 属性指定将数据回发到服务器时浏览器使用的编码类型。 下边是说明: application/x-www-form-urlencoded : 窗体数据被编码为名称/值对。这是标准的编码格式。 multipart/form-data : 窗体数据被编码为...