Регистрация времени выполнения – Конвертация 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// Define the CustomSchemaMessageFilter class that is derived from the MessageFilter class
 2class CustomSchemaMessageFilter : MessageFilter
 3{
 4    private readonly string schema;
 5    public CustomSchemaMessageFilter(string schema)
 6    {
 7        this.schema = schema;
 8    }
 9    // Override the Match() method
10    public override bool Match(INetworkOperationContext context)
11    {
12        return string.Equals(schema, context.Request.RequestUri.Protocol.TrimEnd(':'));
13    }
14}
15
16// Define the CustomSchemaMessageHandler class that is derived from the MessageHandler class
17abstract class CustomSchemaMessageHandler : MessageHandler
18{
19    // Initialize an instance of the CustomSchemaMessageHandler class
20    protected CustomSchemaMessageHandler(string schema)
21    {
22        Filters.Add(new CustomSchemaMessageFilter(schema));
23    }
24}

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

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

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

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

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

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

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

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

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

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

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

Конструктор Configuration() создает экземпляр класса Configuration. После создания конфигурации вызываются методы GetService(), 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.