У меня есть немного кода, который я использовал некоторое время для получения данных с веб-сервера и нескольких месяцев назад, я добавил поддержку сжатия, которая, похоже, хорошо работает для «регулярных» 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» в командной строке для распаковки этих байтов. Однако я попробую.
Можете ли вы проверить, есть ли 51 байт, которые вы получаете, это на самом деле несжатые 51 байты, которые вы просили? – Kylar
И можете ли вы также добавить, какой тип сервера вы нажимаете? Может быть ошибка сервера. – Kylar