2011-12-26 73 views
1

我有一個Android應用程序,讓我這個例外:的Java,MalformedChunkCodingException

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

唯一的例外是從此方法拋出:(目的是寫出來的,從服務器到一個文件中收到的響應)

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(); 
} 

於是我修改上面的代碼:

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() ; 
} 

而且噸該代碼的作品,是什麼導致了這個錯誤和原代碼有什麼問題?

+0

你是通過代理加載?因爲每次我看到這個異常,人們都通過代理加載,並通過刪除緩衝區大小或更改它來糾正錯誤。 – Sephy 2011-12-26 11:11:37

+0

你在說網絡代理嗎? – Vaibhav 2011-12-26 11:20:59

回答

0

我發現這個問題相當老舊,但它顯示出來了,當我搜索MalformedChunkCodingException時。所以這裏有一些提示是怎麼回事。

我只能猜測你的問題是什麼,因爲你不告訴我們在哪一行發生了異常,以及你使用的是哪個版本的org.apache.http.HttpEntity。

第一個MalformedChunkCodingException: CRLF expected at end of chunk真的是這個問題。 當您有chunked http transfer並且至少有一個\r\n在該傳輸中丟失時發生。

有兩種可能的錯誤。首先服務器不發送它們或客戶端丟失它們。

檢查服務器是否正常檢查請求響應是否正常。例如,你可以使用curl看到十六進制的響應:

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\n0d 0a輸出? 這意味着服務器實際上發送了正確的消息。

所以你在讀取響應時可能會丟失一些字節。

我使用了一個調試器併爲MalformedChunkCodingException(Eclipse中的Java異常斷點)設置了一個斷點。我查看了第一次處理傳入響應的堆棧,實際上緩衝區中只有一半響應。

分塊消息是一個流式消息。所以它可能是您在InputStream讀取完整消息之前關閉套接字。 這個例子發生在jersey apache connector

他們有這樣的代碼:

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

其失敗:

JulijanasJezov 18日2016年10月

這種變化不與org.apache.httpcomponents工作: 的HttpClient: 4.5.1+使用分塊傳輸編碼時。這是 ,因爲他們改變了他們關閉連接的方式。

在這種情況下,當response.close()被調用的連接被關閉 和輸入流的緩衝區被清除,然後super.close()函數 不能關閉ChunkedInputStream並導致 org.apache .http.ConnectionClosedException:塊的過早結束 編碼的消息體:預計結束塊。

發生該異常的原因是,在 ChunkedInputStream的結束時,關閉()函數讀取的 分塊消息的其餘部分和它失敗,因爲該流的緩衝器一直當連接已被關閉 清除在response.close()調用。 參考: https://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/ChunkedInputStream.html#close()

的修復這個問題是放的代碼super.close()行 前response.close()。這允許在其緩衝區被清除之前正確關閉流 。

所以,當我發現,在我們的項目我們在Maven POM文件中使用的jersey-apache-connector(舊)和http-client(新)不兼容的版本我的問題得到解決。 (Depenency Hierachy說:httpclient:4.5.3 (managed from 4.5) (ommitted for conflict with 4.5.3)