我已经在Stack Overflow和Google上广泛研究了以下内容而没有任何运气。当我解释我想要实现的目标和我遇到的问题时,请耐心等待。
我正在开发一个SharePoint 2007应用程序,它为浏览器请求的任何图像(jpg,gif,png)添加基本水印。如果图像作为'12 hive'的一部分驻留在文档库或服务器的文件系统中,则无关紧要。 (这是对正在构建的解决方案的简化,我不想让您厌倦不相关的细节。)
由于这需要与所提供的任何图像一起使用,独立于可能在SharePoint上运行的第三方解决方案,我看到的唯一解决方案是编写HTTPModule,挂钩模块的Filter,从中读取图像数据流并用水印版本的图像替换它。无法使用SharePoint的事件接收器,而SharePoint的“服务器端文件处理程序”并未涵盖将这些类型的文件传送到浏览器的所有方案。
尽管使用过滤器拦截和修改基于文本的内容工作正常,但当过滤器包含二进制数据时,自定义过滤器的Write方法会收到损坏的数据。 byte []是正确的,直到在源文件中遇到00,所以它听起来像编码问题(二进制数据??)或HTTPModule过滤器不允许二进制数据,我很难相信。
奇怪的是,当SharePoint从服务器的文件系统读取二进制文件(图像)时,它会正确地通过我的过滤器。但是,从SharePoint文档库中读取二进制文件时,数据已损坏。
为了证实这一点,我进行了以下测试:
从服务器的文件系统和SharePoint文档库中请求1.3MB的TXT文件可以正常工作。从文件系统中读取时,它会到达一个大块。从文档库中读取时,它以32KB大小的块来到。
过滤器可以正确处理驻留在服务器文件系统上的300KB二进制映像。但是,从文档库请求相同的文件会返回损坏的数据。
从文档库请求3KB GIF图像会返回损坏的数据。前10个字节很好,之后数据损坏(源文件中的字节10为0)
如果未启用自定义过滤器,则所请求的文件将始终成功返回给浏览器。
我们的自定义过滤器中的入口点是Write方法。传递给此方法的缓冲区中的数据已损坏。
我知道多个HTTPModule是链接的。我已经尝试将我的自定义模块放在web.config文件的模块列表的开头和末尾,没有任何运气
HTTPModule中用于连接过滤器的相关代码如下:
void context_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.Filter = new ResponseFilter(HttpContext.Current.Response.Filter);
}
ResponseFilter类的实现如下。请注意,除了将源数据写回输出流之外,它实际上并没有做任何事情。
public class ResponseFilter : Stream
{
private MemoryStream internalStream = new MemoryStream();
private Stream responseStream;
public ResponseFilter(Stream outputStream)
{
responseStream = outputStream;
}
public override void Flush()
{
responseStream.Flush();
}
public override void Write(byte[] buffer, int offset, int count)
{
internalStream.Write(buffer, offset, count);
responseStream.Write(buffer, offset, count);
}
public override void Close()
{
responseStream.Close();
}
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override bool CanSeek
{
get { return true; }
}
public override long Length
{
get { return internalStream.Length; }
}
public override long Position
{
get { return internalStream.Position; }
set { internalStream.Position = value; }
}
public override int Read(byte[] buffer, int offset, int count)
{
return internalStream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin direction)
{
return internalStream.Seek(offset, direction);
}
public override void SetLength(long length)
{
internalStream.SetLength(length);
}
}
这个类远非完美,但问题是当Write
方法被击中时,缓冲区中的数据已经损坏。班上其他人目前无所谓。
答案 0 :(得分:0)
这是一个老问题,您可能已经解决了这个问题。如果它仍处于打开状态,您可以考虑进行测试,看看关闭后缓存替换是否可以解决损坏问题。有关详细信息,请参阅ASP.Net Response Filter Clashing with SharePoint 2010 Publishing Site Defaults。这是一个很长的镜头,但也许值得花时间进行测试。