2013-09-13 4 views
0

У меня есть немного кода, который я использовал некоторое время для получения данных с веб-сервера и нескольких месяцев назад, я добавил поддержку сжатия, которая, похоже, хорошо работает для «регулярных» HTTP-ответов, где весь документ содержится в ответе. Однако, похоже, что это не работает, когда я использую заголовок Range.Не удается заставить Java GZIPInputStream читать ответ «gzip» с сервера при использовании заголовка «Range»

Вот код делает реальную работу:

InputStream in = null; 

    int bufferSize = 4096; 

    int responseCode = conn.getResponseCode(); 

    boolean error = 5 == responseCode/100 
     || 4 == responseCode/100; 

    int bytesRead = 0; 

    try 
    { 
     if(error) 
      in = conn.getErrorStream(); 
     else 
      in = conn.getInputStream(); 

     // Buffer the input 
     in = new BufferedInputStream(in); 

     // Handle compressed responses 
     if("gzip".equalsIgnoreCase(conn.getHeaderField("Content-Encoding"))) 
      in = new GZIPInputStream(in); 
     else if("deflate".equalsIgnoreCase(conn.getHeaderField("Content-Encoding"))) 
      in = new InflaterInputStream(in, new Inflater(true)); 

     int n; 
     byte[] buffer = new byte[bufferSize]; 

     // Now, just write out all the bytes 
     while(-1 != (n = in.read(buffer))) 
     { 
      bytesRead += n; 
      out.write(buffer, 0, n); 
     } 
    } 
    catch (IOException ioe) 
    { 
     System.err.println("Got IOException after reading " + bytesRead + " bytes"); 
     throw ioe; 
    } 
    finally 
    { 
     if(null != in) try { in.close(); } 
     catch (IOException ioe) 
     { 
      System.err.println("Could not close InputStream"); 
      ioe.printStackTrace(); 
     } 
    } 

поражая URL с заголовком Accept-Encoding: gzip,deflate,identity работает просто отлично: я могу видеть, что данные возвращаются сервером в сжатом формате, и приведенный выше код распаковал его красиво.

Если я затем добавить Range: bytes=0-50 заголовок, я получаю следующее исключение:

Got IOException after reading 0 bytes 
Exception in thread "main" java.io.EOFException: Unexpected end of ZLIB input stream 
at java.util.zip.InflaterInputStream.fill(InflaterInputStream.java:240) 
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158) 
at java.util.zip.GZIPInputStream.read(GZIPInputStream.java:116) 
at java.io.FilterInputStream.read(FilterInputStream.java:107) 
at [my code]([my code]:511) 

Line 511 в моем коде есть строка, содержащая in.read() вызов. Ответ включает следующие заголовки:

Content-Type: text/html 
Content-Encoding: gzip 
Content-Range: bytes 0-50/751 
Content-Length: 51 

Я проверил, что, если я не пытаться разжать ответ, я на самом деле получить 51 байт в ответ ... это не сбой сервера (по крайней мере, Я могу сказать). Мой сервер (Apache httpd) не поддерживает «deflate», поэтому я не могу проверить другую схему сжатия (по крайней мере, не сейчас).

Я также пытался запросить гораздо больше данных (например, 700 байт из всего 751 байт в целевом ресурсе), и я получаю такую ​​же ошибку.

Есть ли что-то, что мне не хватает?

Обновление Извините, я забыл включить, что я поражаю Apache/2.2.22 на Linux. Я не знаю об ошибках сервера. У меня будет немного проблем с проверкой сжатых байтов, которые я получаю с сервера, поскольку кодировка содержимого «gzip» довольно голая ... например. Я считаю, что не могу просто использовать «gunzip» в командной строке для распаковки этих байтов. Однако я попробую.

+0

Можете ли вы проверить, есть ли 51 байт, которые вы получаете, это на самом деле несжатые 51 байты, которые вы просили? – Kylar

+0

И можете ли вы также добавить, какой тип сервера вы нажимаете? Может быть ошибка сервера. – Kylar

ответ

0

Sigh Переход на другой сервер (возможно, работает Apache/2.2.25) показывает, что мой код действительно работает. Похоже, что на исходном целевом сервере повлияет нынешний перерыв AWS в зоне доступности US-EAST. Я собираюсь помешать этому сетевым ошибкам и закрыть этот вопрос. Спасибо тем, кто предложил предложения.

1

Вы можете использовать «gunzip» для его распаковки, просто имейте в виду, что первых 50 байтов, вероятно, недостаточно для того, чтобы gzip распаковывал что-либо (заголовки, словари и т. Д.). Попробуйте следующее: wget -O- -q <URL> | head -c 50 | zcat с вашим URL-адресом, чтобы узнать, работает ли обычный gzip, где ваш код не работает.

+0

50 байтов не были испытанием, чтобы увидеть, получилось ли меньше, чем это количество байтов ... всего лишь небольшое количество данных, чтобы проверить, будет ли обработка 'Range' работать с gzip. –

 Смежные вопросы

  • Нет связанных вопросов^_^