2009-05-08 2 views
54

При запросе страницы с сжатием Gzip я получаю много из следующих ошибок:HttpWebRequest & Native GZip сжатие

System.IO.InvalidDataException: CRC в GZip сноска, не совпадает с CRC вычисляется из декомпрессированных данные

Я использую родной GZipStream для распаковки, и я рассматриваю это решение. Имея это в виду, есть ли работа для решения этой или другой библиотеки GZip (бесплатно?), Которая будет правильно обрабатывать эту проблему?

Я проверки WebResponse ContentEncoding является GZIP

Update 5/11 упрощенный Snippit

//Caller 
public void SOSampleGet(string url) 
{ 
    // Initialize the WebRequest. 
    webRequest = (HttpWebRequest)WebRequest.Create(url); 
    webRequest.Method = WebRequestMethods.Http.Get; 
    webRequest.KeepAlive = true; 
    webRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; 
    webRequest.Headers.Add("Accept-Encoding", "gzip,deflate"); 
    webRequest.Referer = WebUtil.GetDomain(url); 

    HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();  

    using (Stream stream = GetStreamForResponse(webResponse, READTIMEOUT_CONST)) 
    { 
     //use stream 
    } 
} 

//Method 
private static Stream GetStreamForResponse(HttpWebResponse webResponse, int readTimeOut) 
{ 
    Stream stream; 
    switch (webResponse.ContentEncoding.ToUpperInvariant()) 
    { 
     case "GZIP": 
      stream = new GZipStream(webResponse.GetResponseStream(), CompressionMode.Decompress); 
      break; 
     case "DEFLATE": 
      stream = new DeflateStream(webResponse.GetResponseStream(), CompressionMode.Decompress); 
      break; 

     default: 
      stream = webResponse.GetResponseStream(); 
      stream.ReadTimeout = readTimeOut; 
      break; 
     }  
    return stream; 
} 
+0

Является ли это для конкретного сайта, или это происходит из ответов везде? Если это единственный сайт, может быть, проблема лежит на другой стороне. – MichaelICE

+0

Обратите внимание, что «deflate», в соответствии с спецификацией HTTP, действительно является «zlib» (который обертывает deflate), а не дефлируется вообще (это неправильное название). Из-за [этой путаницы] (http://en.wikipedia.org/wiki/Gzip#Derivatives_and_other_uses) некоторые серверы отправят дефлят, а другие zlib и клиенты должны поддерживать оба (по эвристической догадке) на всякий случай , Тьфу. – Cameron

ответ

-2

Уроженец GZipStream может прочитать сжатый GZIP (RFC 1952) поток, но он может» t обрабатывает формат файла ZIP.

От http://www.geekpedia.com/tutorial190_Zipping-files-using-GZipStream.html:

Недостатком использования класса GZipStream через 3 партия продукта является то, что он имеет ограниченные возможности . Одним из ограничений является то, что вы не можете указать имя файла , который вы размещаете в архиве. Когда GZipStream сжимает файл в ZIP-архив, он берет последовательность байтов из из этого файла, а использует алгоритмы сжатия, которые создают меньшую последовательность байтов. Новая последовательность байтов помещается в новый файл ZIP в . Когда вы открываете ZIP-файл , вы сами откроете архивный файл ; самые популярные ZIP экстракторы (WinZip, WinRar и т. д.) будут показать вам содержимое ZIP в виде файла , который имеет то же самое, что и архив .


EDIT: выше примечание неправильно. GZipStream не создает ZIP-файл. Это не «поток ZIP с одним файлом». Это поток GZIP. Это разные вещи. Нет никакой гарантии, что инструменты, обрабатывающие ZIP-архивы, будут обрабатывать файл .gz.


Для реализации, которая может читать ZIP архивы, в отличие от одного файла ZIP потоков, попробуйте #ziplib (SharpZipLib, formerly NZipLib).

+1

Я не верю, что оригинальный плакат говорит о работе со сжатыми/архивированными файлами. Скорее, прецедент запрашивает веб-страницу при отправке заголовка Accept-Encoding: на сервер, указывая, что клиент поддерживает gzip. Этот заголовок позволяет серверу сжимать содержимое перед отправкой его клиенту, сохраняя пропускную способность. Современные веб-браузеры могут это сделать, и многие серверы настроены соответствующим образом реагировать. –

+0

cwrea правильно – Pat

+1

Вы проверяете, действительно ли сервер отвечает потоком gzip, например, с wirehark? Wireshark может декодировать и проверять ответ, даже если он gzipped. – Andomar

1

См. Мой комментарий выше, но это обычно является признаком поврежденного файла. Если сайт является вашим собственным, замените файл, к которому вы пытаетесь получить доступ.

+0

Не мой сайт, кажется, особенно для нескольких сайтов, которые я запрашиваю. – Pat

2

Вы развеяете и закрываете поток? Попробуйте обернуть свой GZipStream с помощью инструкции.

+0

Его завернутый в Try/Catch/finally вызов Dispose() потока в блоке finally. – Pat

+0

Не могли бы вы также включить код snipet? –

2

Я нашел пример кода, который показывает весь запрос/ответ для GZip-кодированных страниц. Он использует GZipStream.

http://www.know24.net/blog/Decompress+GZip+Deflate+HTTP+Responses.aspx

+0

Ссылка сломана, но я просмотрел ее через archive.org, и основной метод отлично работает :) – Nyerguds

106

Что о WebRequest AutomaticDecompression собственности доступен, так как .net 2? Просто добавьте:

webRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; 

Он также добавляет gzip, дефлятирует заголовок кодировки accept.

См http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.automaticdecompression.aspx

+5

+1 это правильный способ обработки –

+1

+1, Спасибо, человек! : D –

+0

Это похоже на то, что весь запрос зависает на некоторых сайтах ... – Nyerguds

0

для .NET Основные вещи немного сложнее. A GZipStream необходим, поскольку нет свойства (с момента написания) для AutomaticCompression. Смотрите мой ответ здесь: https://stackoverflow.com/a/44508724/2421277

Код от ответа:

var req = WebRequest.CreateHttp(uri); 

/* 
* Headers 
*/ 
req.Headers[HttpRequestHeader.AcceptEncoding] = "gzip, deflate"; 

/* 
* Execute 
*/ 
try 
{ 
    using (var resp = await req.GetResponseAsync()) 
    { 
     using (var str = resp.GetResponseStream()) 
     using (var gsr = new GZipStream(str, CompressionMode.Decompress)) 
     using (var sr = new StreamReader(gsr)) 

     { 
      string s = await sr.ReadToEndAsync(); 
     } 
    } 
} 
catch (WebException ex) 
{ 
    using (HttpWebResponse response = (HttpWebResponse)ex.Response) 
    { 
     using (StreamReader sr = new StreamReader(response.GetResponseStream())) 
     { 
      string respStr = sr.ReadToEnd(); 
      int statusCode = (int)response.StatusCode; 

      string errorMsh = $"Request ({url}) failed ({statusCode}) on, with error: {respStr}"; 
     } 
    } 
}