request.getContentLength()的值为-1的问题解决方案【HttpPost发起】

12 篇文章 0 订阅

1、问题的发现,服务端使用DataInputStream的方式获取流,直接上代码说明

try {
	DataInputStream in = new DataInputStream(request.getInputStream());
	// 将请求消息的实体送到b变量中
	int totalBytes = request.getContentLength();

	byte[] b = new byte[totalBytes];
	in.readFully(b);
	in.close();
	String reqContent = new String(b, "UTF-8");
	respXml = reqContent;
} catch (IOException e) {
	e.printStackTrace();
}

DataInputStream的readFully()需要创新一个与流等长的Byte数组,因为request.getContentLength()的值为-1,读取失败。

2、于是想服务端换一种方式读取,可以规避问题,但是没有解决问题,而且服务端一般是你上游的,你动不了,也不一定会配合你改,以为别的接入可以,为啥你不行,一般都会被怼回来,自讨没趣,但是代码还是要上的。

InputStream inputStream = request.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
StringBuffer msgBuf = new StringBuffer();
String temp = null;
while((temp = br.readLine())!=null){
	msgBuf.append(temp);
}
respXml= msgBuf.toString();

3、针对request.getContentLength()的值为-1,其实就是客户端发送的得数据流的采用的HTTP协议header的Content-Length参数中没有值,于是,准备强制性真进行赋值post.setHeader("Content-Length", xml.getBytes("UTF-8").length+"");,结果提示Caused by: org.apache.http.ProtocolException: Content-Length header already present。于是再次检查客服端代码。InputStreamEntity有四个构造方法,如果不提供长度,默认为-1。因为使用没有length的构造

InputStream inputStream = new ByteArrayInputStream(xml.getBytes("UTF-8"));  
InputStreamEntity inputEntry = new InputStreamEntity(inputStream);

 导致request.getContentLength()的值为-1的构造函数源码如下;

/**
     * Creates an entity with an unknown length.
     * Equivalent to {@code new InputStreamEntity(instream, -1)}.
     *
     * @param instream input stream
     * @throws IllegalArgumentException if {@code instream} is {@code null}
     * @since 4.3
     */
    public InputStreamEntity(final InputStream instream) {
        this(instream, -1);
    }

正确的因为使用下面二个构造函数,创建InputStreamEntity。

   /**
     * Creates an entity with a specified content length.
     *
     * @param instream input stream
     * @param length of the input stream, {@code -1} if unknown
     * @throws IllegalArgumentException if {@code instream} is {@code null}
     */
    public InputStreamEntity(final InputStream instream, final long length) {
        this(instream, length, null);
    }

继续看源码发现post.setEntity(reqentity);InputStreamEntity extends AbstractHttpEntity;而AbstractHttpEntity implements HttpEntity;4.0以后StringEntity extends AbstractHttpEntity,于是是否能用StringEntity来解决问题呢,小试牛刀可以,直接上代码。

HttpEntity reqentity = new StringEntity(xml, ContentType.create("application/xml", "UTF-8"));
post.setEntity(reqentity);

PS:最后有些博客说在header中添加post.setHeader("Accept-Encoding", "identity");我没有成功,从我有些的知识感觉问题是Content-Length没有值或者值不对,不知道跟Accept-Encoding有啥关系,知道的大牛可以留言。最后上一个全乎的代码。

String xml="";
CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse httpResponse = null;
HttpPost post = new HttpPost("http://127.0.0.1:8888/xxx");
		
HttpEntity entity = null;
String result = null;
try {			
/***解决方案一**/
//  HttpEntity reqentity = new StringEntity(xml, ContentType.create("application/xml", "UTF-8"));
//  post.setEntity(reqentity);

/***解决方案二**/
	InputStream inputStream = new ByteArrayInputStream(xml.getBytes("UTF-8"));  
	InputStreamEntity inputEntry = new InputStreamEntity(inputStream,xml.getBytes("utf-8").length);
	post.setEntity(inputEntry);
			

	httpResponse=httpclient.execute(post);
	if(httpResponse.getStatusLine().getStatusCode()==HttpStatus.SC_OK) {
		entity=httpResponse.getEntity();
		result=EntityUtils.toString(entity, "UTF-8");
	}
	EntityUtils.consume(entity);
	httpResponse.close();
			
} catch (Exception e) {

    e.printStackTrace();
}
		
logger.info("返回报文:\r\n"+result);

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值