【发布时间】:2011-02-04 14:03:29
【问题描述】:
我在 Stack Overflow 和 Google 上广泛研究了以下内容,但没有任何运气。在我解释我想要实现的目标和遇到的问题时,请耐心等待。
我正在开发一个 SharePoint 2007 应用程序,该应用程序向浏览器请求的任何图像(jpg、gif、png)添加基本水印。图像是否作为“12 hive”的一部分驻留在文档库或服务器的文件系统中并不重要。 (这是对正在构建的解决方案的简化,我不想用不相关的细节让你厌烦)。
由于这需要处理提供的任何图像,独立于可能在 SharePoint 上运行的第 3 方解决方案,我看到的唯一解决方案是编写一个 HTTPModule,挂钩模块的过滤器,从流并将其替换为图像的水印版本。无法为此使用 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 方法被命中的那一刻,缓冲区中的数据已经损坏。课上的其他人暂时无所谓。
【问题讨论】:
标签: asp.net sharepoint httpmodule