[web] request的Content-Type小结

本文转载自多篇文章,在这里记录一下。

request的Content-Type小结

application/x- www-form-urlencoded是Post请求默认的请求体内容类型,也是form表单默认的类型。Servlet API规范中对该类型的请求内容提供了request.getParameter()方法来获取请求参数值。但当请求内容不是该类型时,需要调用request.getInputStream()或request.getReader()方法来获取请求内容值。

当请求体内容(注意:get请求没有请求体)类型是application/x- www-form-urlencoded时也可以直接调用request.getInputStream()或request.getReader()方法获取到请求内容再解析出具体都参数,但前提是还没调用request.getParameter()方法。此时当request.getInputStream()或request.getReader()获取到请求内容后,无法再调request.getParameter()获取请求内容。即对该类型的请求,三个方法互斥,只能调其中一个。今天遇到一个Controller请求经过Spring MVC 的RequestMapping处理后,只能通过request.getParameter()获取到参数、无法通过request.getInputStream()和request.getReader()读取内容很可能就是因为在请求经过Spring MVC时已调用过request.getParameter()方法的原因。

注意:在一个请求链中,请求对象被前面对象方法中调用request.getInputStream()或request.getReader()获取过内容后,后面的对象方法里再调用这两个方法也无法获取到客户端请求的内容,但是调用request.getParameter()方法获取过内容后,后面的对象方法里依然可以调用它获取到参数的内容。

当请求体内容是其它类型时,比如 multipart/form-data或application/json时,无法通过request.getParameter()获取到请求内容,此时只能通过request.getInputStream()和request.getReader()方法获取请求内容,此时调用request.getParameter()也不会影响第一次调用request.getInputStream()或request.getReader()获取到请求内容。

request.getInputStream()返回请求内容字节流,多用于文件上传,request.getReader()是对前者返回内容的封装,可以让调用者更方便字符内容的处理(不用自己先获取字节流再做字符流的转换操作)。

=========================================

最近做项目时,发现手机客户端通过http协议post方式上传数据到服务端,在服务器端通过request.getInputStream()能获取到相应的数据,但用request.getParameter()却获取不到数据。这是怎么回事呢,后来发现这种情况跟form表单的属性 enctype有关系。 
HTML中的form表单有一个关键属性 enctype=application/x-www-form-urlencoded 或multipart/form-data。

1、enctype=”application/x-www-form-urlencoded”是默认的编码方式,当以这种方式提交数据时,HTTP报文中的内容是: 
Html代码 收藏代码 
POST /post_test.php HTTP/1.1 
Accept-Language: zh-CN 
User-Agent: Mozilla/4.0 
Content-Type: application/x-www-form-urlencoded 
Host: 192.168.12.102 
Content-Length: 42 
Connection: Keep-Alive 
Cache-Control: no-cache

title=test&content=%B3%AC%BC%B6%C5%AE%C9%FA&submit=post+article 

Servlet的API提供了对这种编码方式解码的支持,只需要调用ServletRequest 类中的getParameter()方法就可以得到表单中提交的数据。

2、在传输大数据量的二进制数据时,必须将编码方式设置成enctype=”multipart/form-data”,当以这种方式提交数据时,HTTP报文中的内容是:

Html代码 收藏代码 
POST /post_test.php?t=1 HTTP/1.1 
Accept-Language: zh-CN 
User-Agent: Mozilla/4.0 
Content-Type: multipart/form-data; boundary=—————————7dbf514701e8 
Accept-Encoding: gzip, deflate 
Host: 192.168.12.102 
Content-Length: 345 
Connection: Keep-Alive 
Cache-Control: no-cache

扫描二维码关注公众号,回复: 3903623 查看本文章

—————————–7dbf514701e8 
Content-Disposition: form-data; name=”title” 
test 
—————————–7dbf514701e8 
Content-Disposition: form-data; name=”content” 
…. 
—————————–7dbf514701e8 
Content-Disposition: form-data; name=”submit” 
post article 
—————————–7dbf514701e8– 
如果以这种方式提交数据就要用request.getInputStream()或request.getReader()来获取提交的数据 ,用 request.getParameter()是获取不到提交的数据的。

最后注意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.getInputStream()和request.getReader()在同一个响应中是不能混合使用的,如果混合使用会抛异常的。

============================

 最近项目业务涉及到服务端(Java)与服务端(c++)通信,我是属于java端,c++端通过拼接http请求头向java端发送数据。发现数据可以接收到,但是数据里如果出现+号会将+号转义为空格。经排查发现是因为请求头的Content-Type属性为application/x-www-form-urlencoded,这样会导致url加密,从而将特殊字符转义使得收到的参数不够准确。所以Content-Type 就不能再使用application/x-www-form-urlencoded类型。应改为text/html或text/plain来避免将特殊字符串转义。但是如此一来发送的参数就不是form键值对的形式了。java端无法用传统的接收方法来接收。这个时候就要直接从request的输入流中去取参数。代码如下:

//获取post参数 
StringBuffer sb = new StringBuffer() ; 
InputStream is = request.getInputStream(); 
InputStreamReader isr = new InputStreamReader(is);   
BufferedReader br = new BufferedReader(isr); 
String s = "" ; 
while((s=br.readLine())!=null){ 
sb.append(s) ; 

String str =sb.toString();
--------------------- 
作者:当时年少春衫薄丶 
来源:CSDN 
原文:https://blog.csdn.net/cxfly957/article/details/78785498?utm_source=copy 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/qq_18748337/article/details/83105050
今日推荐