Регистрация времени выполнения – Конвертация HTML – С#
В этой статье вы найдете пример использования пользовательских обработчиков сообщений для конвертации HTML из ZIP-архива в PDF и регистрации времени выполнения этого преобразования.
Иногда для оптимизации производительности может потребоваться узнать время выполнения веб-запроса. Например, вы хотите знать, сколько времени уходит на преобразование HTML из ZIP-архива в PDF.
Конвертировать HTML из ZIP-архива в PDF – регистрация времени выполнения
Создание обработчика сообщений для пользовательской реализации схемы
Давайте создадим собственный обработчик, который вы можете использовать для реализации пользовательской схемы (протокола). Сделайте следующие шаги:
- Используйте необходимое пространство имен, которым является Aspose.Html.Net.
- Определите свой собственный класс CustomSchemaMessageHandler, который будет производным от класса MessageHandler.
- Инициализируйте экземпляр класса CustomSchemaMessageHandler и определите для него свойство Filter.
- Создайте класс CustomSchemaMessageFilter, производный от класса MessageFilter.
- Переопределите метод 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. Выполним следующие шаги:
- Создайте экземпляр класса Configuration.
- Реализуйте пользовательскую схему ZIP. Используйте метод Add(), чтобы добавить ZipFileSchemaMessageHandler в конец конвейера.
- Выполните регистрацию продолжительности. Используйте метод Insert(), чтобы добавить StartRequestDurationLoggingMessageHandler первым в конвейер, и метод Add(), чтобы добавить StopRequestDurationLoggingMessageHandler в конец конвейера.
- Инициализировать документ HTML с указанной конфигурацией.
- Создайте 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.