如何在不加载压缩缓冲区的情况下动态压缩http请求 [英] How to compress http request on the fly and without loading compressed buffer in memory

查看:102
本文介绍了如何在不加载压缩缓冲区的情况下动态压缩http请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将http post请求中的大量数据发送到支持gziped编码请求的服务器。

I need to send voluminous data in a http post request to a server supporting gziped encoded requests.

从简单的

public async Task<string> DoPost(HttpContent content)
{
  HttpClient client = new HttpClient();
  HttpResponseMessage response = await client.PostAsync("http://myUri", content);

  response.EnsureSuccessStatusCode();
  return await response.Content.ReadAsStringAsync();
}

我刚刚添加了预压缩

public async Task<string> DoPost(HttpContent content, bool compress)
{
  if (compress) 
    content= await CompressAsync(content);

  return await DoPost(content);
}

private static async Task<StreamContent> CompressAsync(HttpContent content)
{
  MemoryStream ms = new MemoryStream();
  using (GZipStream gzipStream = new GZipStream(ms, CompressionMode.Compress, true))
  {
    await content.CopyToAsync(gzipStream);
    await gzipStream.FlushAsync();
  }

  ms.Position = 0;
  StreamContent compressedStreamContent = new StreamContent(ms);
  compressedStreamContent.Headers.ContentType = content.Headers.ContentType;
  compressedStreamContent.Headers.Add("Content-Encoding", "gzip");

  return compressedStreamContent;
}

它可以完美工作,但是在发送请求之前,压缩数据已完全加载到内存中。我希望能够在以流方式发送期间动态压缩数据。

It works perfectly but compress data are completly loaded into memory before sending request. I would like to be able to compress data on the fly during sending in a streaming way.

为此,我尝试了以下操作代码:

To do it, I've tried following code:

private static async Task<HttpContent> CompressAsync2(HttpContent content)
{
  PushStreamContent pushStreamContent = new PushStreamContent(async (stream, content2, transport) =>
  {
    using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Compress, true))
    {
      try
      {
        await content.CopyToAsync(gzipStream);
        await gzipStream.FlushAsync();
      }
      catch (Exception exception)
      {
        throw;
      }
    }
  });
  pushStreamContent.Headers.ContentType = content.Headers.ContentType;
  pushStreamContent.Headers.Add("Content-Encoding", "gzip");

  return pushStreamContent;
}

但它永远不会超出CopyToAsync(gzipStream)。 FlushAsync永远不会执行,也不会抛出异常,并且Fiddler看不到任何帖子开始。

but it never goes out of CopyToAsync(gzipStream). FlushAsync is never executed and no exception is thrown and Fiddler don't see any post started.

我的问题是:


  • 为什么CompressAsync2不起作用?

  • 如何在发送过程中快速压缩并且不将压缩缓冲区加载到内存中?

任何帮助将不胜感激。

推荐答案

尝试使用WebAPIContrib https:// github中的CompressedContent类。 com / WebApiContrib / WebAPIContrib / blob / master / src / WebApiContrib / Content / CompressedContent.cs

Try using the CompressedContent class from WebAPIContrib https://github.com/WebApiContrib/WebAPIContrib/blob/master/src/WebApiContrib/Content/CompressedContent.cs

public async Task<string> DoPost(HttpContent content)
{
  HttpClient client = new HttpClient();
  HttpResponseMessage response = await client.PostAsync("http://myUri", 
                                 new CompressedContent(content,"gzip"));

  response.EnsureSuccessStatusCode();
  return await response.Content.ReadAsStringAsync();
}

只能在.net 4.5上流式传输内容。 NET Web版本的HttpWebRequest始终缓冲发送的内容。

P.S. that this will only stream the content on .net 4.5. The .net 4 version of HttpWebRequest always buffers sent content.

P.P.S。为每个请求创建一个新的HttpClient并不是使用HttpClient的最佳方法。这样做将强制为每个请求创建一个新的TCP连接。

P.P.S. Creating a new HttpClient for each request is not the best way to use HttpClient. Doing this will force a new TCP connection to be created for each request.

这篇关于如何在不加载压缩缓冲区的情况下动态压缩http请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆