我正在为web-api应用程序进行一些压缩/解压缩。
由于网络上的multiple articles和questions 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对象,我需要一个实际流的句柄。
答案 0 :(得分: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()
时,您将收到 un 缓冲流。