【问题标题】:Seamless decompressing the request content in web api无缝解压web api中的请求内容
【发布时间】:2013-06-19 01:34:56
【问题描述】:

我正在为 web-api 应用程序进行一些压缩/解压缩。

感谢网络上的multiple articlesquestions posted here,我已经实现了大部分。

但是,我仍然被困在一个甚至还没有受到质疑的问题上。

简而言之,我需要支持大量数据的流式传输,包括响应和请求,并且都是压缩的。我已经实现了DelegatingHandler 并创建了 2 个HttpContent 类,一个用于压缩内容(响应),另一个用于解压缩内容(请求)。

使用以下代码压缩响应完美

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

如您所见,我有义务将原始请求作为流读取,然后再将其复制到解压缩流并将其进一步发送到管道中。

当大量数据发布到服务时,这可能不是一个好习惯。 那么现在的问题是,这是正确的方法吗?我一直在寻找一种无缝的方式来做到这一点。

我正在考虑实现Blocking Stream(适应新的 TAP),但我再次陷入困境,因为 HttpContent 完全是 TAP,这意味着一切都返回一个 Task 对象,我需要一个实际 Stream 的句柄。

【问题讨论】:

    标签: asp.net-web-api compression


    【解决方案1】:

    我可以回答你的部分问题。当您调用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() 时,您将收到一个 un 缓冲流。

    【讨论】:

    • 有趣。我记得几周前读到过这项政策。但是就这一点而言,我仍然会在将其推入减压流之前对其进行缓冲。我希望新的 HttpClient 和可移植压缩库能给我一些见解,但到目前为止还没有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-08
    • 2014-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    相关资源
    最近更新 更多