问题描述:
今天在测试产品的时候发现使用HttpUrlClient发送POST表单数据,当数据量>=1M的时,后台报错,原因分析如下:
一、HTTP协议对数据大小的限制
根据RFC规定,HTTP1.1本身并没有对GET和POST方法进行参数大小限制,但是不同的浏览器和WEB服务器对数据大小会做限制,比如:
不同浏览器对URL长度的限制(字符)
IE : 2803 Firefox:65536 Chrome:8182 Safari:80000 Opera:190000
WEB服务器对POST数据长度限制:
Tomcat默认大小为2M,可以修改配置:maxPostSize="0",取消对数据大小的限制。
二、Tomcat默认大小为2M,为什么超过1M数据就会报错
经过查看,发现在使用HttpUrlClient与后台交互时,POST数据处理如下:
1.使用 String data = "content=" + URLEncode.encode("XXXXX......", "utf-8"),对数据进行编码;
2.在传递数据时outputStream.writer(data.getByte("utf-8"));
这个过程进行了两次UTF-8编码使字节数变大。问题解决了,但借此机会了解下WEB中的编码方式。以下内容学习总结与《深入分析Java WEB技术内幕》。
三、WEB中的编解码
URL编解码:(URL中存在中文的情况)
http://localhost:8080/examples/servlets/servlet/屌丝男士?name=屌丝男士
http:协议 localhost:域名 8080:端口 /examples/servlets/servlet/屌丝男士:URI examples:ContextPath servlets/servlet/:ServeltPath 屌丝男士:PageInfo name=屌丝男士:QueryString
通过谷歌浏览器观察:
其中PageInfo采用了UTF-8编码,而QueryString也采用了UTF-8编码。至于为什么会“%”,根据RFC3986可知浏览器编码URL将非ASCII字符按照某种编码格式编程16进制数字后将每个16进制表示的字节前加上“%”。
a.不同的浏览器对 pageInfo 的编码方式不同,Tomcat对URL中URI的解码字符集是在connector中定义的,默认为ISO-8859-1。<Connector URIEncoding="UTF-8"/>
b. QueryString的解码字符集是在是在 Header 中 Content-Type 中,通过 charset 定义的,默认为 IOS-8859-1, 但是要使用 Content-Type 中定义的编码,就要在 connector 中进行如下的设置:
<Connector useBodyEncodingForURI="true"/>
URL 的编码和解码过程比较复杂,并不都由我们自己能完全控制,所以尽量在 URL 中使用非 ASCII 字符。
POST 表单的编解码
POST 表单类型的参数传递方式与 QueryStirng 方式不同,是通过 HTTP Body 方式传递到服务器端的,它根据 Content-Type 中的 charset 规定的格式进行编码,在服务器端也通过 Content-Type 中对字符编码方式进行解码。
HTTP Body 中的编解码
响应的内容通过 Header 中的 Content-Type 返回客户端,浏览器通过 Content-Type 的 charset 进行解码。如果返回的 Content-Type 中没有设置 charset 值,那么浏览器将根据 HTML 的
<meta HTTP-equiv="Content-Type" content="text/html; charset=utf-8" />
来进行解码。