压缩webapi POST的正确方法

时间:2015-05-18 18:08:06

标签: c# asp.net asp.net-web-api

我有一个webform页面,它调用webapi方法来保存一些数据。我正在使用HttpClient进行调用并执行webapi。

我尝试使用webAPI压缩将巨大的xml发布到API。 我基本上用这两个网站作为参考: http://www.ronaldrosier.net/blog/2013/07/16/implement_compression_in_aspnet_web_apihttp://benfoster.io/blog/aspnet-web-api-compression

API正在运行,它正确地触发了处理程序。我在服务器端的网络表单上试图压缩和发布对象时遇到了一些问题。

这是我尝试过的代码:

bool Error = false;
//Object to post. Just an example...
PostParam testParam = new PostParam()
{
  inputXML = "<xml>HUGE XML</xml>",
  ID = 123
};

try
{
  using (var client = new HttpClient())
  {
    using (var memStream = new MemoryStream())
    {
       var data = new DataContractJsonSerializer(typeof(PostParam));
       data.WriteObject(memStream, testParam);
       memStream.Position = 0;
       var contentToPost = new StreamContent(this.Compress(memStream));
       contentToPost.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
       contentToPost.Headers.Add("Content-Encoding", "gzip");
       var response = client.PostAsync(new Uri("http://myapi/SAVE"), contentToPost).Result;

       var dataReceived = response.EnsureSuccessStatusCode();

       dynamic results;
       if (dataReceived.IsSuccessStatusCode)
       {
         results = JsonConvert.DeserializeObject<dynamic>(dataReceived.Content.ReadAsStringAsync().Result);
         try
         {
           this.Error = results.errors.Count == 0;
         }
         catch { }
     }
  }
   }
}
catch
{
  this.Error = true;
}


//Compress stream
private MemoryStream Compress(MemoryStream ms)
        {
            byte[] buffer = new byte[ms.Length];
            // Use the newly created memory stream for the compressed data.
            GZipStream compressedzipStream = new GZipStream(ms, CompressionMode.Compress, true);
            compressedzipStream.Write(buffer, 0, buffer.Length);
            // Close the stream.
            compressedzipStream.Close();
            MemoryStream ms1 = new MemoryStream(buffer);
            return ms1;
        }

当我执行上面的代码时,它不会抛出任何错误,并且在处理程序中,request.Content.ReadAsStringAsync()。结果是一个巨大的\ 0 \ 0 \ 0 \ 0 \ 0 \ 0 ...

拜托,你们能告诉我我做错了什么吗?如何正确地将带有XML的压缩对象发送到API?

谢谢

2 个答案:

答案 0 :(得分:21)

这就是我想出的。有可能因为您没有设置接受gzip编码的请求,使用HttpClientHandler.AutomaticDecompression,您可能会收回编码结果而不处理它。可能不是这样。无论如何,我可以确认这个例子是有效的。它是另一个API控制器。在幕后,我已经设置WebApi接受gzip编码并解压缩,然后再将其移交给控制器动作;这是通过扩展DelegatingHandler类来完成的。我让IIS做响应压缩。我使用WebApi 2。

public async Task<IHttpActionResult> Get()
{
    List<PersonModel> people = new List<PersonModel>
    {
        new PersonModel
        {
            FirstName = "Test",
            LastName = "One",
            Age = 25
        },
        new PersonModel
        {
            FirstName = "Test",
            LastName = "Two",
            Age = 45
        }
    };
    using (HttpClientHandler handler = new HttpClientHandler())
    {
        handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
        using (HttpClient client = new HttpClient(handler, false))
        {
            string json = JsonConvert.SerializeObject(people);
            byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
            MemoryStream ms = new MemoryStream();
            using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress, true))
            {
                gzip.Write(jsonBytes, 0, jsonBytes.Length);
            }
            ms.Position = 0;
            StreamContent content = new StreamContent(ms);
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            content.Headers.ContentEncoding.Add("gzip");
            HttpResponseMessage response = await client.PostAsync("http://localhost:54425/api/Gzipping", content);
            IEnumerable<PersonModel> results = await response.Content.ReadAsAsync<IEnumerable<PersonModel>>();
            Debug.WriteLine(String.Join(", ", results));
        }
    }
    return Ok();
}

答案 1 :(得分:2)

您始终可以通过IIS使用HttpCompression http://www.iis.net/configreference/system.webserver/httpcompression

<httpCompression
  directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
<dynamicTypes>
  <add mimeType="text/*" enabled="true" />
  <add mimeType="message/*" enabled="true" />
  <add mimeType="application/javascript" enabled="true" />
  <add mimeType="*/*" enabled="false" />
</dynamicTypes>
<staticTypes>
  <add mimeType="text/*" enabled="true" />
  <add mimeType="message/*" enabled="true" />
  <add mimeType="application/javascript" enabled="true" />
  <add mimeType="*/*" enabled="false" />
</staticTypes>
</httpCompression>

然后,HTTP客户端必须通过发送适当的HTTP Accept-encoding标头来启动压缩内容的通信。

httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));

这是一个例子: http://benfoster.io/blog/aspnet-web-api-compression