Поделиться через


Пример: модуль "Подложка изображения"

Фабио Йеон

Это пример того, как написать собственный модуль (C++), который будет динамически вставлять настроенную пользователем подложку в обслуживаемый образ, а также как расширить конфигурацию и средство пользовательского интерфейса inetmgr, чтобы упростить администрирование нового модуля.

Модуль водяного знака имеет следующие возможности:

  • Его можно включить или отключить на любом уровне конфигурации (например, на сайте, в приложении, виртуальном каталоге и т. д.).
  • Он может помечать форматы изображений JPG, GIF и PNG.
  • Подложка может иметь формат JPG, GIF или PNG. Изображение подложки не обязательно должно быть того же типа, что и изображение для подложки (т. е. изображение подложки GIF можно использовать для подложки запроса изображения PNG).
  • Можно настроить расположение изображения водяного знака ("верхний левый", "верхний правый", "нижний левый", "нижний правый", "центр", а также параметры "плитка" и "растянуть"). Только параметр "растянуть" изменит или изменит изображение водяного знака при необходимости.
  • Можно также выбрать уровень прозрачности изображения водяного знака от 0 до 100 %.

Чтобы скомпилировать пример, необходимо установить пакет SDK платформы для Windows Vista или Windows Server 2008. Файл проекта, включенный в пример, можно загрузить в Visual Studio 2005 или 2008.

Исходный код для этих примеров доступен здесь.

Модуль водяного знака

Первым компонентом этого примера является сам модуль водяного знака. Это собственный модуль C++, который проверяет, как обрабатываются запросы, и если тип MIME запроса указывает, что это изображение, он динамически применяет к образу подложку, настроенную пользователем, и заменяет исходящий образ. Все это выполняется прозрачно в модуле, который выполняется после обработчика запросов. Чтобы проиллюстрировать это, выполните приведенные ниже действия.

Схема, показывающая дерево принятия решений от обработчика запросов до маркера воды для изображений. Если есть изображение из обработчика запросов, отправляется новое изображение, в противном случае отправляется исходный образ.

  1. Логика кода довольно проста:
  2. При первой загрузке модуля он регистрируется для события после RQ_EXECUTE_REQUEST_HANDLER, которое указывает системе, что он хочет получать уведомления сразу после запуска обработчика запросов.
  3. Теперь, когда событие после RQ_EXECUTE_REQUEST_HANDLER будет запущено, оно извлекает конфигурацию для своего пути. Если он не включен, он не будет ничего делать дальше по запросу и залогу.
  4. Если он включен, он проверка заголовок ответа Content-Type и проверить, является ли он типом изображения. Если это не так, это будет залог.
  5. Если это изображение, оно увидит, является ли ответ буфером или дескриптором файла. Если это будет позже, он загрузит изображение в память, применит подложку на основе настроенных пользователем параметров (т. е. файл изображения, положение, прозрачность), сохранит полученное изображение в буфер в памяти, заменит данные ответа буфером в памяти и вернет.
  6. Буфер в памяти будет освобожден в методе "Dispose" модуля.

Использование классов CImage ATL делает загрузку и обработку изображения очень простым, тем более что он может легко управлять различными форматами изображений.

Теперь в этом примере есть несколько предостережения, и их следует учитывать, особенно если вы хотите использовать его в "реальной" рабочей среде:

  • Код работает только для тех типов изображений, в которых ответ находится в дескрипторове файла. Вместо этого объект HTTP_RESPONSE может содержать изображение в последовательности буферов. Интересным упражнением было бы создание реализации IStream в памяти, которая обертывает буферы в объекте ответа (watch для нескольких ответов буфера!).
  • Модуль не пытается изменить или обновить заголовок ответа "ETag". Это означает, что результирующий образ с водяными знаками будет считаться "реальным" для клиента (как и должно), но также может запутать логику кэширования клиента. Правильная реализация этого параметра потребуется изменить ETag, чтобы учесть конфигурацию образа с водяной меткой. Например, в текущей реализации, если вы добавили водяной знак "WatermarkFileA" в положение "UpperLeft" с прозрачностью "50 %", а затем сделали запрос в браузере (т. е. Internet Обозреватель), IE будет кэшировать это изображение на основе различных заголовков ответов. Если вы изменили конфигурацию модуля водяного знака (т. е. изменили изображение, положение или прозрачность) и снова запросили файл (через "F5"), так как образ кэшировался IE, вместо того чтобы запрашивать изображение, он будет просто выполнять запрос "HEAD", отправляя сведения об этом изображении. Обработчик запроса, не зная, что образ изменился, ответит, что отправленный ранее ответ по-прежнему действителен, и завершит обработку запроса. К сожалению, в этом случае модуль подложки не будет иметь возможности запустить и перезапустить подложку образа с его новой конфигурацией, поэтому клиент с радостью будет отображать старое изображение с водяными знаками. Правильное исправление для этого позволит модулю подложки каким-то образом включить свою конфигурацию в "ETag" ответа, чтобы любые изменения в образе или модуле водяного знака привели к аннулированию любого кэшированного образа клиента и его повторной обработке.

Конфигурация

Настройка модуля водяного знака выполняется с помощью нового раздела в пространстве имен system.webServer. Файл схемы выглядит следующим образом:

<configSchema> 
 <sectionSchema name="system.webServer/watermark"> 
  <attribute name="enabled" type="bool" defaultValue="false" /> 
  <attribute name="watermarkImage" type="string" /> 
  <attribute name="transparency" type="uint" defaultValue="50" validationType="integerRange" validationParameter="0,100" /> 
  <attribute name="position" type="enum" defaultValue="LowerRight" > 
    <enum name="UpperLeft" value="0" /> 
    <enum name="UpperRight" value="1" /> 
    <enum name="LowerLeft" value="2" /> 
    <enum name="LowerRight" value="3" /> 
    <enum name="Center" value="4" /> 
    <enum name="Stretch" value="5" /> 
    <enum name="Tile" value="6" /> 
  </attribute> 
 </sectionSchema> 
</configSchema>

Файл "watermark.xml" должен быть удален в %windir%\system32\inetsrv\config\schema каталог, чтобы он вступил в силу, а также добавить определение раздела в файл "applicationhost.config" в пространство имен system.webServer:

<section name="Watermark" overrideModeDefault="Allow" />

Чтобы использовать модуль, необходимо установить модуль в глобальном списке модулей system.webServer\globalModules:

<add name="WatermarkModule" image="c:\Watermark\Watermark.dll" />

А в списке модулей для приложения — system.webServer\modules:

<add name="WatermarkModule" />

Inetmgr

Наряду с примером модуля представляет собой набор управляемых классов, которые являются подключаемыми модулями управления для нового средства администрирования пользовательского интерфейса Inetmgr. Существуют различные другие документации по написанию и расширению нового "Inetmgr", которые доступны здесь. Короче говоря, чтобы использовать их, необходимо выполнить сборку, добавить библиотеки DLL в глобальный кэш сборок (глобальный кэш сборок) и добавить в файл следующую конфигурацию %windir%\system32\inetsrv\config\administration.config :

В коллекцию <moduleProviders> добавьте следующую запись:

<add name="Watermark" type="WatermarkServer.WatermarkModuleProvider, Watermarkserver, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5f6f8f3f74d67fe4" />

Добавьте следующую строку в коллекцию <modules> :

<add name="Watermark" />

Перезапустите средство, и на сайте должен быть доступен новый значок.