在SharePoint HTTPModule中使用筛选器拦截二进制数据会返回损坏的数据

时间:2011-02-04 14:03:30

标签: asp.net sharepoint httpmodule

我已经在Stack Overflow和Google上广泛研究了以下内容而没有任何运气。当我解释我想要实现的目标和我遇到的问题时,请耐心等待。

我正在开发一个SharePoint 2007应用程序,它为浏览器请求的任何图像(jpg,gif,png)添加基本水印。如果图像作为'12 hive'的一部分驻留在文档库或服务器的文件系统中,则无关紧要。 (这是对正在构建的解决方案的简化,我不想让您厌倦不相关的细节。)

由于这需要与所提供的任何图像一起使用,独立于可能在SharePoint上运行的第三方解决方案,我看到的唯一解决方案是编写HTTPModule,挂钩模块的Filter,从中读取图像数据流并用水印版本的图像替换它。无法使用SharePoint的事件接收器,而SharePoint的“服务器端文件处理程序”并未涵盖将这些类型的文件传送到浏览器的所有方案。

尽管使用过滤器拦截和修改基于文本的内容工作正常,但当过滤器包含二进制数据时,自定义过滤器的Write方法会收到损坏的数据。 byte []是正确的,直到在源文件中遇到00,所以它听起来像编码问题(二进制数据??)或HTTPModule过滤器不允许二进制数据,我很难相信。

奇怪的是,当SharePoint从服务器的文件系统读取二进制文件(图像)时,它会正确地通过我的过滤器。但是,从SharePoint文档库中读取二进制文件时,数据已损坏。

为了证实这一点,我进行了以下测试:

  1. 从服务器的文件系统和SharePoint文档库中请求1.3MB的TXT文件可以正常工作。从文件系统中读取时,它会到达一个大块。从文档库中读取时,它以32KB大小的块来到。

  2. 过滤器可以正确处理驻留在服务器文件系统上的300KB二进制映像。但是,从文档库请求相同的文件会返回损坏的数据。

  3. 从文档库请求3KB GIF图像会返回损坏的数据。前10个字节很好,之后数据损坏(源文件中的字节10为0)

  4. 如果未启用自定义过滤器,则所请求的文件将始终成功返回给浏览器。

  5. 我们的自定义过滤器中的入口点是Write方法。传递给此方法的缓冲区中的数据已损坏。

  6. 我知道多个HTTPModule是链接的。我已经尝试将我的自定义模块放在web.config文件的模块列表的开头和末尾,没有任何运气

  7. 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方法被击中时,缓冲区中的数据已经损坏。班上其他人目前无所谓。

1 个答案:

答案 0 :(得分:0)

这是一个老问题,您可能已经解决了这个问题。如果它仍处于打开状态,您可以考虑进行测试,看看关闭后缓存替换是否可以解决损坏问题。有关详细信息,请参阅ASP.Net Response Filter Clashing with SharePoint 2010 Publishing Site Defaults。这是一个很长的镜头,但也许值得花时间进行测试。