2013-05-21 41 views
10

HTTPポストリクエストで膨大なデータをgzipedエンコード要求をサポートするサーバに送信する必要があります。シンプルHTTPリクエストを圧縮してメモリに圧縮されたバッファをロードせずに圧縮する方法

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(); 
} 

から始まっ

は、私はちょうどそれが完璧に動作しますが、データはcompletly要求を送信する前にメモリにロードされている圧縮前圧縮

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; 
} 

を追加しました。私はは、ストリーミング方法で送信中にオンザフライでデータを圧縮できるようにしたいと考えています。それを行うには

、私は次のコードを試してみた:

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は開始された投稿を見ません。

私の質問は以下のとおりです。

  • CompressAsync2は動作しないのはなぜ?
  • 送信中に圧縮バッファをメモリにロードせずにオンザフライで圧縮する方法はありますか?

ご協力いただければ幸いです。

+1

'PushStreamContent'は(現在)' async' lambdasをサポートしていません。 –

+0

@Stephen Cleary:あなたはそうだ、私はチェックしておくべきだった!また、PushStreamContentからSerializeToStreamAsyncをオーバーロードすることはできません(内部のみが多すぎます)。あなたは解決策を見られますか? – MuiBienCarlota

+0

Humm、 '' PushStreamContent'を修正して(https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Net.Http.Formatting/PushStreamContent.cs)、 '非同期ラムダ。数ヶ月間、私の「todo」リストに載っていました。ちょうどそれを知りませんでした。 –

答えて

12

P.S. 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(); 
} 

CompressedContentクラスを使用してみてくださいこれは.net 4.5でのみコンテンツをストリーミングすることになります。 .net 4バージョンのHttpWebRequestは、常に送信されたコンテンツをバッファします。

P.P.S.要求ごとに新しいHttpClientを作成することは、HttpClientを使用する最良の方法ではありません。これを行うと、要求ごとに新しいTCP接続が強制的に作成されます。

+0

本当にinterresting link:ありがとうございます。私は.Net 4.0(XPが必要)にとどまる必要があります。 .Net 4.0用にコンパイルしても.Net 4.5がインストールされているときにストリーム配信できると思いますか? – MuiBienCarlota

+0

質問の簡潔さのためにローカルのHttpClientを作成しました。 – MuiBienCarlota

+0

@MuiBienCarlotaわかりません。私の推測ははいですが、あなたはテストする必要があります。 HttpClientに関して...クール、私はちょうどそれをたくさん見ると私はそれを刻む使命にあります;-) –

関連する問題