1

私は、web-api アプリケーションの圧縮/解凍に取り組んでいます。

ウェブ上の複数の記事とここに投稿された質問のおかげで、私はすでにそのほとんどを実装しています。

しかし、私はまだ 1 つの問題に行き詰まっています。

つまり、応答と要求の両方で、圧縮された大量のデータのストリーミングをサポートする必要があります。私はすでに を実装し、DelegatingHandler2 つのクラスを作成しましたHttpContent。1 つは圧縮されたコンテンツ (応答) 用で、もう 1 つは解凍されたコンテンツ (要求) 用です。

次のコードを使用すると、応答の圧縮が完全に機能します

protected override Task SerializeToStreamAsync(System.IO.Stream stream, System.Net.TransportContext context)
{
    Stream compressionStream = this.Compressor.CreateCompressionStream(stream);

    return this.OriginalContent.CopyToAsync(compressionStream).ContinueWith(task =>
    {
        if (compressionStream != null)
        {
            compressionStream.Dispose();
        }
    });
}

圧縮ストリームを作成し、元のコンテンツを圧縮ストリームにコピーします。ただし、リクエストの解凍に関しては、現在次のコードを使用しています。

protected override Task SerializeToStreamAsync(System.IO.Stream stream, System.Net.TransportContext context)
{
    Stream compressionStream = 
      this.Compressor.CreateDecompressionStream(
                                       this.OriginalContent.ReadAsStreamAsync().Result);

    return compressionStream.CopyToAsync(stream).ContinueWith(task =>
    {
        if (compressionStream != null)
        {
            compressionStream.Dispose();
        }
    });
}

ご覧のとおり、元の要求をストリームとして読み取ってから、圧縮解除ストリームにコピーし、パイプラインのさらに下に送信する必要があります。

大量のデータがサービスに送信される場合、これは適切な方法ではない可能性があります。さて、質問ですが、これは正しい方法ですか?これを行うためのシームレスな方法を探していました。

ブロッキング ストリーム(新しい TAP に適応) を実装することを考えていましたが、HttpContent が完全に TAP であるため、再び行き詰まりました。つまり、すべてが Task オブジェクトを返し、実際のストリームへのハンドルが必要です。

4

1 に答える 1

0

あなたの質問の一部に答えることができます。を呼び出すthis.OriginalContent.ReadAsStreamAsync()までに、リクエストのコンテンツはすでにバッファリングされています。これは、既定で Web API がすべての着信要求をバッファーするためです。しかし、ええ、より大きなリクエストの場合、このバッファモードを使用しないことは理にかなっています. ただし、このデフォルトのバッファ ポリシーは変更できます。

以下の例 (WebHost を使用している場合。これは Selfhost では機能しません):

config.Services.Replace(typeof(IHostBufferPolicySelector), new CustomBufferPolicySelector());

public class CustomBufferPolicySelector : WebHostBufferPolicySelector
{
    // This method gets called for every incoming request. You can inspect the HttpContextBase instance
    // to decide whether you would want buffered/non-buffered way of handling individual requests.
    public override bool UseBufferedInputStream(object hostContext)
    {
        HttpContextBase contextBase = hostContext as HttpContextBase;

        //by default, this returns 'true'  
        return base.UseBufferedInputStream(hostContext);
    }

    // just fyi
    public override bool UseBufferedOutputStream(HttpResponseMessage response)
    {
        return base.UseBufferedOutputStream(response);
    }
}

上記のカスタム ポリシーを設定した後、 を実行すると、バッファリングされていないストリームthis.OriginalContent.ReadAsStreamAsync()を受信します。

于 2013-06-18T17:28:54.210 に答える