如何实现HTTP响应过滤器一次操作整个内容,无需分块
正如其他几篇文章中所述(请参阅下面的参考资料)我试图创建响应过滤器,以便修改由另一个Web应用程序生成的内容。
我将基本的字符串转换逻辑工作并封装到源自公共FilterBase的Filters中。但是,逻辑必须对完整内容进行操作,而不是对内容进行操作。因此,我需要在写入时缓存块,并在完成所有写入时执行过滤器。
如下所示,我创建了一个从MemoryStream派生的新ResponseFilter。在写入时,内容缓存到另一个MemoryStream。在Flush上,现在在MemoryStream中的完整内容将转换为字符串,并且Filter逻辑将启动。然后将修改后的内容写回原始流。
但是,在每个第二个请求(基本上是在前一个请求上实例化新的Filter)时,正在执行前一个过滤器的Flush方法。此时,由于_cachedStream为空,应用程序在_outputStream.Write()方法上崩溃。
活动顺序如下:
第一次请求
调用Write方法
调用Flush方法
调用Close方法
调用Close方法
此时,应用程序返回并显示正确的内容。
第二个请求
调用Flush方法
应用程序在_outputStream.Write上崩溃。 ArgumentOutOfRangeException(offset)。
继续崩溃(在Visual Studio中)
调用Close方法
我有几个问题:
为什么Close叫两次?
为什么在关闭后调用Flush?
对于Jay的观点,可以在完全读取流之前调用Flush,过滤器逻辑应该驻留在哪里?在关闭?在Flush但是“如果关闭”?
对一次处理整个内容的响应过滤器的正确实现是什么?
注意:如果我不重写Close方法,我会遇到完全相同的行为(减去Close事件)。
public class ResponseFilter : MemoryStream
{
private readonly Stream _outputStream;
private MemoryStream _cachedStream = new MemoryStream(1024);
private readonly FilterBase _filter;
public ResponseFilter (Stream outputStream, FilterBase filter)
{
_outputStream = outputStream;
_filter = filter;
}
// Flush is called on the second, fourth, and so on, page request (second request) with empty content.
public override void Flush()
{
Encoding encoding = HttpContext.Current.Response.ContentEncoding;
string cachedContent = encoding.GetString(_cachedStream.ToArray());
// Filter the cached content
cachedContent = _filter.Filter(cachedContent);
byte[] buffer = encoding.GetBytes(cachedContent);
_cachedStream = new MemoryStream();
_cachedStream.Write(buffer, 0, buffer.Length);
// Write new content to stream
_outputStream.Write(_cachedStream.ToArray(), 0, (int)_cachedStream.Length);
_cachedStream.SetLength(0);
_outputStream.Flush();
}
// Write is called on the first, third, and so on, page request.
public override void Write(byte[] buffer, int offset, int count)
{
// Cache the content.
_cachedStream.Write(buffer, 0, count);
}
public override void Close()
{
_outputStream.Close();
}
}
// Example usage in a custom HTTP Module on the BeginRequest event.
FilterBase transformFilter = new MapServiceJsonResponseFilter();
response.Filter = new ResponseFilter(response.Filter, transformFilter);
参考文献:
如何在站点范围内部署托管HTTP模块?
创建多个(15+)HTTP响应过滤器,继承与组合w /注入
没有找到相关结果
已邀请:
2 个回复
奥李
我还没有找到上述其他问题的答案,所以我不会在此时将此答案标记为例外。
抚驰