Я тщательно изучил следующее на Stack Overflow и Google без какой-либо удачи.Терпите меня, пока я объясняю, чего я пытаюсь достичь и с какой проблемой я сталкиваюсь.
Я занимаюсь разработкой приложения SharePoint 2007, которое добавляет базовый водяной знак к любому изображению (jpg, gif, png), запрошенному браузером.Не имеет значения, находится ли изображение в библиотеке документов или файловой системе сервера как часть «куста 12».(Это упрощение строящегося решения, я не хочу утомлять вас ненужными подробностями).
Поскольку это потребуется для работы с любым обслуживаемым изображением, независимо от стороннего производителя.Решения, которые могут работать в SharePoint, единственное решение, которое я вижу, - это написать HTTPModule, подключить фильтр модуля, прочитать данные изображения из потока и заменить его версией изображения с водяным знаком.Для этого невозможно использовать приемники событий SharePoint, а «обработчики файлов» на стороне сервера SharePoint не охватывают все сценарии доставки файлов такого типа в браузер.
Несмотря на перехват и изменение текстового содержимого с использованием фильтраработает нормально, когда фильтр содержит двоичные данные, метод записи пользовательского фильтра получает поврежденные данные.Байт [] корректен до тех пор, пока в исходном файле не встретится 00, поэтому звучит так, будто либо проблема кодирования (двоичных данных ??), либо фильтры HTTPModule не разрешают двоичные данные, в которые мне трудно поверить.
Странная вещь в том, что когда SharePoint читает двоичный файл (изображение) из файловой системы сервера, он проходит через мой фильтр должным образом.Однако в момент считывания двоичного файла из библиотеки документов SharePoint данные будут повреждены.
Чтобы подтвердить это, я провел следующие тесты:
Запрос1.3MB TXT-файл из файловой системы сервера и библиотеки документов SharePoint работает нормально.При чтении из файловой системы он поступает одним большим фрагментом.При чтении из библиотеки документов он поступает в виде блоков размером 32 КБ.
Запрос двоичного изображения объемом 300 КБ, находящегося в файловой системе сервера, обрабатывается фильтром.Однако запрос того же файла из библиотеки документов возвращает поврежденные данные.
Запрос изображения GIF размером 3 КБ из библиотеки документов возвращает поврежденные данные.Первые 10 байтов исправны, после чего данные становятся поврежденными (байт 10 равен 0 в исходном файле)
Если пользовательский фильтр не включен, то запрошенные файлы всегда успешно возвращаются вбраузер.
Точкой входа в наш пользовательский фильтр является метод Write.Данные в буфере, которые передаются этому методу, уже повреждены.
Я понимаю, что несколько 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
Метод попадания данных в буфер уже поврежден.Остальная часть класса в настоящее время не имеет значения.