I need to send voluminous data in a http post request to a server supporting gziped encoded requests.
Starting from a simple
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();
}
I've just added a pre compression
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;
}
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.
My questions are:
Any help would be greatly appreciated.
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();
}
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. 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With