Регистрация времени выполнения – Конвертация HTML – С#

В этой статье вы найдете пример использования пользовательских обработчиков сообщений для конвертации HTML из ZIP-архива в PDF и регистрации времени выполнения этого преобразования.

Иногда для оптимизации производительности может потребоваться узнать время выполнения веб-запроса. Например, вы хотите знать, сколько времени уходит на преобразование HTML из ZIP-архива в PDF.

Конвертировать HTML из ZIP-архива в PDF – регистрация времени выполнения

Создание обработчика сообщений для пользовательской реализации схемы

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

  1. Используйте необходимое пространство имен, которым является Aspose.Html.Net.
  2. Определите свой собственный класс CustomSchemaMessageHandler, который будет производным от класса MessageHandler.
  3. Инициализируйте экземпляр класса CustomSchemaMessageHandler и определите для него свойство Filter.
  4. Создайте класс CustomSchemaMessageFilter, производный от класса MessageFilter.
  5. Переопределите метод Match() класса MessageFilter для реализации пользовательского поведения обработчика сообщений.

В следующем фрагменте кода показано, как создать класс CustomSchemaMessageHandler:

 1// Monitor network requests by custom protocol in C # using schema-based message filter and handler
 2
 3// Define the CustomSchemaMessageFilter class that is derived from the MessageFilter class
 4class CustomSchemaMessageFilter : MessageFilter
 5{
 6    private readonly string schema;
 7    public CustomSchemaMessageFilter(string schema)
 8    {
 9        this.schema = schema;
10    }
11    // Override the Match() method
12    public override bool Match(INetworkOperationContext context)
13    {
14        return string.Equals(schema, context.Request.RequestUri.Protocol.TrimEnd(':'));
15    }
16}
17
18// Define the CustomSchemaMessageHandler class that is derived from the MessageHandler class
19abstract class CustomSchemaMessageHandler : MessageHandler
20{
21    // Initialize an instance of the CustomSchemaMessageHandler class
22    protected CustomSchemaMessageHandler(string schema)
23    {
24        Filters.Add(new CustomSchemaMessageFilter(schema));
25    }
26}

Конструктор CustomSchemaMessageHandler(schema) создает экземпляр объекта CustomSchemaMessageHandler и принимает схему в качестве параметра. Метод Add() добавляет объект CustomSchemaMessageFilter в конец коллекции. Метод Match() проверяет, удовлетворяет ли контекст критериям фильтрации.

Создание ZipFileSchemaMessageHandler для работы с ZIP-архивами

В следующем фрагменте кода показано, как создать класс ZipFileSchemaMessageHandler для работы с ZIP-архивами:

 1// Handle zip file protocol requests in c#
 2
 3// Define the ZipFileSchemaMessageHandler class that is derived from the CustomSchemaMessageHandler class
 4class ZipFileSchemaMessageHandler : CustomSchemaMessageHandler
 5{
 6    private readonly Archive archive;
 7
 8    public ZipFileSchemaMessageHandler(Archive archive) : base("zip-file")
 9    {
10        this.archive = archive;
11    }
12
13    // Override the Invoke() method
14    public override void Invoke(INetworkOperationContext context)
15    {
16        string pathInsideArchive = context.Request.RequestUri.Pathname.TrimStart('/').Replace("\\", "/");
17        Stream stream = GetFile(pathInsideArchive);
18
19        if (stream != null)
20        {
21            // If a resource is found in the archive, then return it as a Response
22            ResponseMessage response = new ResponseMessage(HttpStatusCode.OK);
23            response.Content = new StreamContent(stream);
24            response.Headers.ContentType.MediaType = MimeType.FromFileExtension(context.Request.RequestUri.Pathname);
25            context.Response = response;
26        }
27        else
28        {
29            context.Response = new ResponseMessage(HttpStatusCode.NotFound);
30        }
31
32        // Invoke the next message handler in the chain
33        Next(context);
34    }
35
36    Stream GetFile(string path)
37    {
38        ArchiveEntry result = archive
39            .Entries
40            .FirstOrDefault(x => x.Name == path);
41        return result?.Open();
42    }
43}

В приведенном выше примере реализован поиск ресурса (zip-архива) по его URI. Если ресурс найден, метод FromFileExtension() возвращает MimeType ресурса.

Обработчик сообщений для регистрации времени выполнения веб-запроса

В следующем фрагменте кода показано, как создать StartRequestDurationLoggingMessageHandler и StopRequestDurationLoggingMessageHandler для регистрации времени, затраченного на выполнение веб-запроса.

 1// Track and log HTTP request durations using C# message handlers
 2
 3// Define the RequestDurationLoggingMessageHandler class that is derived from the MessageHandler class
 4abstract class RequestDurationLoggingMessageHandler : MessageHandler
 5{
 6    private static ConcurrentDictionary<Url, Stopwatch> requests = new ConcurrentDictionary<Url, Stopwatch>();
 7
 8    protected void StartTimer(Url url)
 9    {
10        requests.TryAdd(url, Stopwatch.StartNew());
11    }
12
13    protected TimeSpan StopTimer(Url url)
14    {
15        Stopwatch timer = requests[url];
16        timer.Stop();
17        return timer.Elapsed;
18    }
19}
20
21class StartRequestDurationLoggingMessageHandler : RequestDurationLoggingMessageHandler
22{
23    // Override the Invoke() method
24    public override void Invoke(INetworkOperationContext context)
25    {
26        // Start the stopwatch
27        StartTimer(context.Request.RequestUri);
28
29        // Invoke the next message handler in the chain
30        Next(context);
31    }
32}
33
34class StopRequestDurationLoggingMessageHandler : RequestDurationLoggingMessageHandler
35{
36    // Override the Invoke() method
37    public override void Invoke(INetworkOperationContext context)
38    {
39        // Stop the stopwatch
40        TimeSpan duration = StopTimer(context.Request.RequestUri);
41
42        // Print the result
43        Debug.WriteLine($"Elapsed: {duration:g}, resource: {context.Request.RequestUri.Pathname}");
44
45        // Invoke the next message handler in the chain
46        Next(context);
47    }
48}

Добавление обработчиков сообщений в конвейер

Ключевой концепцией работы обработчиков сообщений является объединение их в цепочку. Мы создали несколько обработчиков сообщений и должны добавить их в конвейер в определенном порядке, чтобы реализовать пример регистрации времени преобразования HTML из ZIP-архива в PDF. Выполним следующие шаги:

  1. Создайте экземпляр класса Configuration.
  2. Реализуйте пользовательскую схему ZIP. Используйте метод Add(), чтобы добавить ZipFileSchemaMessageHandler в конец конвейера.
  3. Выполните регистрацию продолжительности. Используйте метод Insert(), чтобы добавить StartRequestDurationLoggingMessageHandler первым в конвейер, и метод Add(), чтобы добавить StopRequestDurationLoggingMessageHandler в конец конвейера.
  4. Инициализировать документ HTML с указанной конфигурацией.
  5. Создайте PDF-устройство и преобразуйте HTML в PDF.
 1// Implement custom zip schema with request duration logging using C# message handlers
 2
 3// Add this line before you try to use the 'IBM437' encoding
 4System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
 5
 6// Prepare path to a source zip file
 7string documentPath = Path.Combine(DataDir, "test.zip");
 8
 9// Prepare path for converted file saving
10string savePath = Path.Combine(OutputDir, "zip-to-pdf-duration.pdf");
11
12// Create an instance of the Configuration class
13using Configuration configuration = new Configuration();
14INetworkService service = configuration.GetService<INetworkService>();
15MessageHandlerCollection handlers = service.MessageHandlers;
16
17// Custom Schema: ZIP. Add ZipFileSchemaMessageHandler to the end of the pipeline
18handlers.Add(new ZipFileSchemaMessageHandler(new Archive(documentPath)));
19
20// Duration Logging. Add the StartRequestDurationLoggingMessageHandler at the first place in the pipeline
21handlers.Insert(0, new StartRequestDurationLoggingMessageHandler());
22
23// Add the StopRequestDurationLoggingMessageHandler to the end of the pipeline
24handlers.Add(new StopRequestDurationLoggingMessageHandler());
25
26// Initialize an HTML document with specified configuration
27using HTMLDocument document = new HTMLDocument("zip-file:///test.html", configuration);
28
29// Create the PDF Device
30using PdfDevice device = new PdfDevice(savePath);
31
32// Render ZIP to PDF
33document.RenderTo(device);

Конструктор Configuration() создает экземпляр класса Configuration. После создания конфигурации вызываются методы GetService<INetworkService>(), MessageHandlers.Add() и MessageHandlers.Insert(). Методы Insert() и Add() добавляют пользовательские обработчики сообщений в коллекцию существующих обработчиков сообщений. На рисунке показана цепочка обработчиков сообщений для этого примера:

Текст “Цепочка обработчиков сообщений”

Примечание. Конструктор HTMLDocument(address, configuration) принимает абсолютный путь к ZIP-архиву. Но все связанные ресурсы имеют относительные пути в документе HTML и в коде примера.

Вы можете скачать полные примеры и файлы данных с GitHub.

Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.