Java,MalformedChunkCodingException [英] Java, MalformedChunkCodingException

查看:264
本文介绍了Java,MalformedChunkCodingException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Android应用程序,给了我这个例外:

I have an Android Application that gives me this exception:

org.apache.http.MalformedChunkCodingException: CRLF expected at end of chunk

此方法引发异常:(目的是将从服务器接收到的响应写到文件中.)

The exception is thrown from this method: (Purpose is to write out the response received from the server to a file.)

public static void getResponseBodyForServerData(
    final HttpEntity entity) throws IOException, ParseException {

    if (entity == null) {
        throw new IllegalArgumentException("HTTP entity may not be null");
    }
    InputStream instream = entity.getContent();

    if (instream == null) {
        return;
    }
    File file = new File(Environment.getExternalStorageDirectory() + 
        "/foo/Response.txt");

    if (!file.exists()) {
        file.createNewFile();
    }
    OutputStream out = new FileOutputStream(file);
    byte buf[] = new byte[1024];
    int len;
    while ((len = instream.read(buf)) > 0)
        out.write(buf, 0, len);
    out.flush();
    out.close();
}

所以我将上面的代码修改为:

So then I modified the above code to:

public static void getResponseBodyForServerData(
    final HttpEntity entity) throws IOException, ParseException {

    if (entity == null) {
        throw new IllegalArgumentException("HTTP entity may not be null");
    }
    InputStream instream = entity.getContent();
    InputStreamReader inputStreamReader = new InputStreamReader(
        instream, "UNICODE") ;

    if (instream == null) {
        return;
    }
    File file = new File(Environment.getExternalStorageDirectory() + 
        "/foo/Response.txt");
    if (!file.exists()) {
        file.createNewFile();
    }

    BufferedReader bufferedReader = new BufferedReader(inputStreamReader) ;
    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(
        new FileOutputStream(file),"UNICODE")) ;

    String singleLine = null ;

    while((singleLine = bufferedReader.readLine()) != null) {
        bufferedWriter.write(singleLine) ;
    }

    bufferedWriter.flush() ;
    bufferedWriter.close() ;
}

然后代码起作用,什么原因导致该错误以及原始代码有什么问题?

And then the code works, What causes that error and what is wrong with the original code?

推荐答案

当我搜索MalformedChunkCodingException时,我看到这个问题已经很老了,但还是出现了.因此,这里有一些提示.

I see that the question is rather old, nevertheless it showed up, when I searched for MalformedChunkCodingException. So here are some hints what's going on.

我只能猜测您的问题是因为您没有告诉我们异常发生在哪一行以及您使用的是哪个版本的org.apache.http.HttpEntity.

I can only guess what your problem was since you don't tell us in which line the exception occured and which version of org.apache.http.HttpEntity you use.

第一个 MalformedChunkCodingException:在块末尾预期出现CRLF 确实是问题所在.当您具有分块的HTTP传输并且至少有一个 \ r \ n时,就会发生这种情况在该传输中丢失.

First MalformedChunkCodingException: CRLF expected at end of chunk really is the problem. It occures when you have a chunked http transfer and at least one \r\n is missing in that transfer.

有两个可能的错误.首先,服务器不发送它们,或客户端释放它们.

There are two possible errors. First the server does not send them or the client looses them.

要检查服务器是否正常,请检查请求响应是否正常.例如,您可以使用curl以十六进制查看响应:

To check if the server is ok check if the request response is ok. For example you can use curl to see the response in hex:

curl -ivs --raw http://host:port/somePath/toResource --trace /dev/stdout

以下是一些示例输出:

00a0: 30 31 22 7d 5d 0d 0a 30 0d 0a 0d 0a             01"}]..0....

在输出中看到 \ r \ n 0d 0a 吗?这意味着服务器实际上发送了正确的消息.

See the \r\n as 0d 0a in the output? That means the server actually sends a correct message.

因此,您可能在读取响应时丢失了一些字节.

So you probably loose some bytes while reading the response.

我使用了调试器,并为MalformedChunkCodingException(Eclipse中的Java异常断点)设置了一个断点.我查看了第一次处理传入响应的堆栈,实际上缓冲区中只有响应的一半.

I used a debugger and set a breakpoint for MalformedChunkCodingException (Java Exception Breakpoint in Eclipse). I looked in the stack where the incoming response was processed the first time and really there was only half of the response in the buffer.

分块消息是流消息.因此,可能是您在InputStream阅读完整的消息之前关闭了套接字.例如,这发生在球衣apache连接器中.

A chunked message is a streaming message. So it may be that you close the socket before the InputStream has read the complete message. This for example happened in the jersey apache connector.

他们有以下代码:

return new FilterInputStream(inputStream) {
    @Override
    public void close() throws IOException {
        response.close();
        super.close();
    }

失败了:

JulijanasJezov于2016年10月18日

JulijanasJezov on 18 Oct 2016

此更改不适用于org.apache.httpcomponents:httpclient:使用分块传输编码时为4.5.1+.这是因为他们改变了关闭连接的方式.

This change does not work with the org.apache.httpcomponents: httpclient: 4.5.1+ when using chunked transfer encoding. This is because they have changed the way they close the connection.

在这种情况下,当调用response.close()时,连接已关闭然后清除输入流的缓冲区,然后执行super.close()函数无法关闭ChunkedInputStream并导致org.apache.http.ConnectionClosedException:块的过早结束编码的邮件正文:预计关闭大块.

In this case when response.close() is called the connection is closed and the input stream's buffer is cleared, then super.close() function is not able to close the ChunkedInputStream and results in org.apache.http.ConnectionClosedException: Premature end of chunk coded message body: closing chunk expected.

发生异常的原因是:ChunkedInputStream,close()函数读取其余的分块的消息,它失败,因为流的缓冲区已被在response.close()调用中关闭连接后清除.参考: https://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/ChunkedInputStream.html#close()

The reason of the exception occurring is that upon close of ChunkedInputStream, the close() function reads the remainder of the chunked message and it fails because the buffer of the stream has been cleared when the connection has been closed in response.close() call. Reference: https://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/ChunkedInputStream.html#close()

此问题的解决方法是将super.close()代码行放在前面response.close().这样可以关闭流在清除其缓冲区之前正确操作.

The fix to this problem is putting super.close() line of code before the response.close(). This allows for the stream to be closed correctly before its buffer has been cleared.

当我发现我们的项目中使用了 jersey-apache-connector (旧)和我们的Maven pom中的http-client (新).(Deperency Hierachy说: httpclient:4.5.3(从4.5开始管理)(省略了与4.5.3的冲突))

So my problem was solved when I found out that in our project we used incompatible versions of jersey-apache-connector (old) and http-client (new) in our maven pom. (Depenency Hierachy said: httpclient:4.5.3 (managed from 4.5) (ommitted for conflict with 4.5.3))

这篇关于Java,MalformedChunkCodingException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆