Как сжать HttpWebRequest POST

Я пытаюсь отправить данные на сервер, который принимает сжатые данные. Код ниже работает очень хорошо, но он несжатый. Я не работал с сжатием или Gzip beofre, поэтому любая помощь аппроксимируется.

HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
  request.Timeout = 600000;
  request.Method = verb;  // POST    
  request.Accept = "text/xml";

  if (!string.IsNullOrEmpty(data))
  {
    request.ContentType = "text/xml";        

    byte[] byteData = UTF8Encoding.UTF8.GetBytes(data);
    request.ContentLength = byteData.Length;       

    // Here is where I need to compress the above byte array using GZipStream

    using (Stream postStream = request.GetRequestStream())
    {
      postStream.Write(byteData, 0, byteData.Length);         
    }
  }      

  XmlDocument xmlDoc = new XmlDocument();
  HttpWebResponse response = null;
  StreamReader reader = null;
  try
  {
    response = request.GetResponse() as HttpWebResponse;
    reader = new StreamReader(response.GetResponseStream());
    xmlDoc.LoadXml(reader.ReadToEnd());
  }

Я собираю весь массив байтов? Нужно ли добавлять другие заголовки или удалять ту, которая уже существует?

Спасибо!

-Скотт

Ответы

Ответ 1

Чтобы ответить на заданный вами вопрос, с помощью сжатых данных POST, все, что вам нужно сделать, это обернуть поток запросов потоком gzip

 using (Stream postStream = request.GetRequestStream())
 {
    using(var zipStream = new GZipStream(postStream, CompressionMode.Compress))
    {
        zipStream.Write(byteData, 0, byteData.Length);         
    }
 }

Это совсем другое, чем запрос на ответ gzip, что гораздо более распространено.

Ответ 2

В Page_Load событие:

        Response.AddHeader("Content-Encoding", "gzip");

И для создания сжатых запросов:

HttpWebRequest и GZip Http Responses от Рика Стралла

Ответ 3

Я также получил сообщение "Не могу закрыть поток до тех пор, пока все байты не записаны", используя код, похожий на tnyfst. Проблема заключалась в том, что у меня было:

request.ContentLength = binData.Length;

где binData - это мои сырые данные перед сжатием. Очевидно, что длина сжатого содержимого будет отличаться, поэтому я просто удалил эту строку и закончил с этим кодом:

using (GZipStream zipStream = new GZipStream(request.GetRequestStream(), CompressionMode.Compress))
{
    zipStream.Write(binData, 0, binData.Length);
}

Ответ 4

Попробуйте этот метод расширения. Поток будет оставлен открытым (см. Конструктор GZipStream). По завершении сжатия положение потока устанавливается на 0.

public static void GZip(this Stream stream, byte[] data)
{
    using (var zipStream = new GZipStream(stream, CompressionMode.Compress, true))
    {
        zipStream.Write(data, 0, data.Length);
    }
    stream.Position = 0;
}

Вы можете использовать следующий тест:

[Test]
public void Test_gzip_data_is_restored_to_the_original_value()
{
    var stream = new MemoryStream();
    var data = new byte[]{1,2,3,4,5,6,7,8,9,10};

    stream.GZip(data);

    var decompressed = new GZipStream(stream, CompressionMode.Decompress);

    var data2 = new byte[10];
    decompressed.Read(data2,0,10);

    Assert.That(data, Is.EqualTo(data2));
}

Для получения дополнительной информации см. http://msdn.microsoft.com/en-us/library/hh158301(v=vs.110).aspx