Java, MalformedChunkCodingException - PullRequest
       0

Java, MalformedChunkCodingException

1 голос
/ 26 декабря 2011

У меня есть приложение Android, которое выдает мне это исключение:

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

И затем код работает. Что вызывает эту ошибку и что не так с исходным кодом?

1 Ответ

1 голос
/ 04 июля 2017

Я вижу, что вопрос довольно старый, тем не менее, он обнаружился, когда я искал MalformedChunkCodingException. Вот несколько подсказок о том, что происходит.

Я могу только догадываться, в чем заключалась ваша проблема, поскольку вы не сообщаете нам, в какой строке произошло исключение и какую версию org.apache.http.HttpEntity вы используете.

Сначала MalformedChunkCodingException: CRLF expected at end of chunk действительно проблема. Это происходит, когда у вас есть кусочный http-перевод , и по крайней мере один \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\n как 0d 0a в выводе? Это означает, что сервер действительно отправляет правильное сообщение.

Таким образом, вы, вероятно, теряете несколько байтов при чтении ответа.

Я использовал отладчик и установил точку останова для MalformedChunkCodingException (точка останова Java Exception в Eclipse). Я посмотрел в стек, где входящий ответ был обработан в первый раз, и на самом деле в буфере была только половина ответа.

Чанкованное сообщение является потоковым сообщением. Так что может случиться так, что вы закроете сокет до того, как InputStream прочитает полное сообщение . Это, например, произошло в джерси-апачском разъеме .

У них был этот код:

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

, что не удалось:

JulijanasJezov 18 октября 2016

Это изменение не работает с компонентами org.apache.http: httpclient: 4.5.1+ при использовании кодирования передачи по частям. Это потому что они изменили способ, которым они закрывают соединение.

В этом случае при вызове response.close () соединение закрывается и буфер входного потока очищается, затем функция super.close () не может закрыть ChunkedInputStream и приводит к org.apache.http.ConnectionClosedException: преждевременное завершение фрагмента тело закодированного сообщения: ожидается закрытие чанка.

Причиной возникновения исключения является то, что при закрытии ChunkedInputStream, функция close () читает остаток от chunked сообщение, и оно терпит неудачу, потому что буфер потока был очищается, когда соединение было закрыто при вызове response.close (). Ссылка: https://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/ChunkedInputStream.html#close()

Решением этой проблемы является добавление строки кода super.close () перед response.close (). Это позволяет закрывать поток правильно, прежде чем его буфер был очищен.

Таким образом, моя проблема была решена, когда я узнал, что в нашем проекте мы использовали несовместимые версии jersey-apache-connector (old) и http-client (new) мавен пом (Зависимость Иерахи сказал: httpclient:4.5.3 (managed from 4.5) (ommitted for conflict with 4.5.3))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...