Ho bisogno di inviare dati voluminosi in una richiesta di post http a un server che supporta richieste codificate gziped.Come comprimere la richiesta HTTP al volo e senza caricare il buffer compresso in memoria
Partendo da un semplice
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();
}
Ho appena aggiunto un pre compressione
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;
}
funziona perfettamente, ma comprimono i dati sono completamente caricati in memoria prima di inviare richiesta. I vorrebbe essere in grado di comprimere i dati al volo durante l'invio in streaming.
Per farlo, ho provato seguente codice:
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;
}
ma non passa mai di copyToAsync (GZipStream). FlushAsync non viene mai eseguito e non viene generata alcuna eccezione e Fiddler non vede alcun post avviato.
Le mie domande sono:
- Perché CompressAsync2 non funziona?
- Come comprimere al volo durante l'invio e senza caricare il buffer compresso in memoria?
Qualsiasi aiuto sarebbe molto apprezzato.
'PushStreamContent' non supporta (attualmente)' asd' lambda. –
@Stephen Cleary: hai ragione, avrei dovuto controllare! E non posso derivare da PushStreamContent per sovraccaricare SerializeToStreamAsync (troppi solo interni). riesci a vedere una soluzione? – MuiBienCarlota
Humm, potrebbe essere più semplice prendere ['PushStreamContent' e modificarlo] (https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Net.Http.Formatting/PushStreamContent.cs) per supportare' async' lambda. È stato nella mia lista di "cose da fare" da alcuni mesi, ma non ci sono riuscito. –