Использование фильтра в SharePoint HTTPModule для перехвата двоичных данных возвращает поврежденные данные - PullRequest
2 голосов
/ 04 февраля 2011

Я тщательно изучил следующее на Stack Overflow и Google без какой-либо удачи.Терпите меня, пока я объясняю, чего я пытаюсь достичь и с какой проблемой я сталкиваюсь.

Я занимаюсь разработкой приложения SharePoint 2007, которое добавляет базовый водяной знак к любому изображению (jpg, gif, png), запрошенному браузером.Не имеет значения, находится ли изображение в библиотеке документов или файловой системе сервера как часть «куста 12».(Это упрощение строящегося решения, я не хочу утомлять вас ненужными подробностями).

Поскольку это потребуется для работы с любым обслуживаемым изображением, независимо от стороннего производителя.Решения, которые могут работать в SharePoint, единственное решение, которое я вижу, - это написать HTTPModule, подключить фильтр модуля, прочитать данные изображения из потока и заменить его версией изображения с водяным знаком.Для этого невозможно использовать приемники событий SharePoint, а «обработчики файлов» на стороне сервера SharePoint не охватывают все сценарии доставки файлов такого типа в браузер.

Несмотря на перехват и изменение текстового содержимого с использованием фильтраработает нормально, когда фильтр содержит двоичные данные, метод записи пользовательского фильтра получает поврежденные данные.Байт [] корректен до тех пор, пока в исходном файле не встретится 00, поэтому звучит так, будто либо проблема кодирования (двоичных данных ??), либо фильтры HTTPModule не разрешают двоичные данные, в которые мне трудно поверить.

Странная вещь в том, что когда SharePoint читает двоичный файл (изображение) из файловой системы сервера, он проходит через мой фильтр должным образом.Однако в момент считывания двоичного файла из библиотеки документов SharePoint данные будут повреждены.

Чтобы подтвердить это, я провел следующие тесты:

  1. Запрос1.3MB TXT-файл из файловой системы сервера и библиотеки документов SharePoint работает нормально.При чтении из файловой системы он поступает одним большим фрагментом.При чтении из библиотеки документов он поступает в виде блоков размером 32 КБ.

  2. Запрос двоичного изображения объемом 300 КБ, находящегося в файловой системе сервера, обрабатывается фильтром.Однако запрос того же файла из библиотеки документов возвращает поврежденные данные.

  3. Запрос изображения GIF размером 3 КБ из библиотеки документов возвращает поврежденные данные.Первые 10 байтов исправны, после чего данные становятся поврежденными (байт 10 равен 0 в исходном файле)

  4. Если пользовательский фильтр не включен, то запрошенные файлы всегда успешно возвращаются вбраузер.

  5. Точкой входа в наш пользовательский фильтр является метод Write.Данные в буфере, которые передаются этому методу, уже повреждены.

  6. Я понимаю, что несколько HTTPModules объединены в цепочки.Я попытался поместить свой пользовательский модуль как в начале, так и в конце списка модулей в файле 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 Метод попадания данных в буфер уже поврежден.Остальная часть класса в настоящее время не имеет значения.

1 Ответ

0 голосов
/ 12 мая 2011

Это старый вопрос, и вы могли решить эту проблему. Если он все еще открыт, вы можете попробовать проверить, решает ли проблема с повреждением отключение замены после кэширования. Подробнее см. Фильтр ответов ASP.Net с настройками сайта публикации SharePoint 2010 по умолчанию . Это длинный выстрел, но, возможно, стоит потратить время на тестирование.

...