Распакуйте HTTP-ответ GZIP в Java - PullRequest
9 голосов
/ 19 марта 2010

Я пытаюсь распаковать HTTP-ответ GZIPed с помощью GZIPInputStream. Однако у меня всегда возникает одно и то же исключение при попытке прочитать поток: java.util.zip.ZipException: invalid bit length repeat

Мой заголовок HTTP-запроса:

GET www.myurl.com HTTP/1.0\r\n
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.2) Gecko/20100115 Firefox/3.6\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3\r\n
Accept-Encoding: gzip,deflate\r\n
Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7\r\n
Keep-Alive: 115\r\n
Connection: keep-alive\r\n
X-Requested-With: XMLHttpRequest\r\n
Cookie: Some Cookies\r\n\r\n

В конце заголовка ответа HTTP я получаю path=/Content-Encoding: gzip, за которым следует ответ gziped.

Я пытался распаковать 2 похожих кода:

ОБНОВЛЕНИЕ: В следующих кодах tBytes = (the string after 'path=/Content-Encoding: gzip').getBytes ();

GZIPInputStream  gzip = new GZIPInputStream (new ByteArrayInputStream (tBytes));

StringBuffer  szBuffer = new StringBuffer ();

byte  tByte [] = new byte [1024];

while (true)
{
    int  iLength = gzip.read (tByte, 0, 1024); // <-- Error comes here

    if (iLength < 0)
        break;

    szBuffer.append (new String (tByte, 0, iLength));
}

И этот, который я получаю на этом форуме:

InputStream     gzipStream = new GZIPInputStream   (new ByteArrayInputStream (tBytes));
Reader          decoder    = new InputStreamReader (gzipStream, "UTF-8");//<- I tried ISO-8859-1 and get the same exception
BufferedReader  buffered   = new BufferedReader    (decoder);

Полагаю, это ошибка кодировки.

С уважением,

bill0ute

Ответы [ 2 ]

9 голосов
/ 19 марта 2010

Вы не показываете, как вы получаете tBytes, который вы используете для настройки потока gzip здесь:

GZIPInputStream  gzip = new GZIPInputStream (new ByteArrayInputStream (tBytes));

Одним из объяснений является то, что вы включаете полный HTTP-ответ в tBytes. Вместо этого это должен быть только контент после заголовков HTTP.

Другое объяснение состоит в том, что ответом является chunked .

edit : Вы берете данные после строки кодирования содержимого в качестве тела сообщения. Однако в соответствии со спецификацией HTTP 1.1 поля заголовка не имеют определенного порядка, так что это очень опасно.

Как объяснено в этой части HTTP-спецификации , тело сообщения запроса или ответа идет не после определенного поля заголовка, а после первой пустой строки :

Запрос (раздел 5) и Ответ (раздел 6) сообщения используют общий формат сообщения RFC 822 [9] для передающие лица (полезная нагрузка сообщение). Оба типа сообщений состоят из стартовой линии, ноль или более поля заголовка (также известный как "заголовки"), пустая строка (т.е. строка с ничем предшествующим CRLF) с указанием конца заголовка поля и, возможно, тело сообщения.

Вы до сих пор не показали, как именно вы составляете tBytes, но на данный момент я думаю, что вы ошибочно включаете пустую строку в данные, которые вы пытаетесь распаковать. Тело сообщения начинается после символов CRLF пустой строки.

Могу ли я предложить вам использовать библиотеку httpclient вместо извлечения тела сообщения?

1 голос
/ 09 января 2014

Ну, есть проблема, которую я вижу здесь;

int  iLength = gzip.read (tByte, 0, 1024);

Используйте следующее, чтобы исправить это;

        byte[] buff = new byte[1024];
byte[] emptyBuff = new byte[1024];
                            StringBuffer unGzipRes = new StringBuffer();

                            int byteCount = 0;
                            while ((byteCount = gzip.read(buff, 0, 1024)) > 0) {
                                // only append the buff elements that
                                // contains data
                                unGzipRes.append(new String(Arrays.copyOf(
                                        buff, byteCount), "utf-8"));

                                // empty the buff for re-usability and
                                // prevent dirty data attached at the
                                // end of the buff
                                System.arraycopy(emptyBuff, 0, buff, 0,
                                        1024);
                            }
...