Як працює Viewer

Життєвий цикл запиту документа

Doconut відображає документи як розбиті на сторінки зображення, що подаються через middleware ASP.NET Core. Розуміння життєвого циклу — відкриття, токен, запити сторінок, закриття — пояснює майже всю поведінку, яку ви спостерігатимете, включаючи повідомлення про помилки.

Три взаємодіючі частини

  • Viewer — публічний сервіс, який ви інжектуєте. Він відкриває документи та повертає токени сесії.
  • Сесія документа — об’єкт на боці сервера, що зберігає завантажений документ, індексований токеном у IMemoryCache.
  • Middleware Doconut — додається за допомогою UseDoconut(); відповідає на кожен запит, який робить віджет браузера (pages, thumbnails, search, annotations, …), завжди автентифікований токеном.

Viewer без стану — за задумом

Viewer є sealed, не містить стану документа для кожного запиту і навмисно не реалізує IDisposable. Сесії існують незалежно в менеджері сесій і очищуються вичерпанням кешу або явним викликом CloseDocument(token).

Ви більше не створюєте його вручну. AddDoconut() реєструє його як транзитний сервіс; інжектуйте його там, де потрібно:

csharp
app.MapPost("/api/open", async (string fileName, Viewer viewer) =>
{
    var token = await viewer.OpenDocumentAsync($"files/{fileName}");
    return Results.Content(token, "text/plain");
});

У застосунку MVC беріть його як параметр конструктора; у Razor‑виді використовуйте @inject Doconut.Viewer Viewer. Кеші, що належать застосунку і містять екземпляри Viewer, більше не потрібні — і більше не є правильними, оскільки вони не містять нічого, що варто кешувати.

Що відбувається всередині OpenDocumentAsync

  1. Ліцензійна перевірка. Відхилена або прострочена версія ліцензії (чорний список, підроблена або збірка поза вікном оновлення ліцензії) миттєво генерує LicenseException з причиною відхилення у повідомленні — відкриття ніколи не деградує безшумно для недійсної (на відміну від відсутньої) ліцензії. Ліцензія типу Temporary або підписки, прострочена за календарем, є винятком: вона не генерує виключення — переходить у водяний знак.
  2. Створення сесії. Фабрика переглядача вибирає відповідний переглядач формату за розширенням файлу та завантажує документ (див. Rendering Pipeline). Сесія зберігається в IMemoryCache під новим GUID‑токеном з ковзним терміном дії — DocOptions.TimeOut хвилин, за замовчуванням 60. Кожен запит сторінки скидає таймер.
  3. Реєстрація безпеки. При UnsafeMode = false (за замовчуванням) токен прив’язується до ASP.NET сесії виклику: в сесію записується маркер secure-{token}, тому лише браузерна сесія, яка відкрила документ, може запитувати його сторінки.
  4. Токен повертається. Це єдина облікова дані для всього подальшого.

Окремого кроку прогрівання немає. Попередня бібліотека надавала InitCache() для цієї мети; вона більше не існує, і нічого її не замінює.

Три перевантаження відрізняються лише вхідними даними: шлях до файлу, шлях до файлу плюс конфігурація формату (PdfConfig, WordConfig, …) або Stream плюс FileInfo, розширення якого визначає формат.

Як віджет отримує сторінки

Віджет клієнта викликає middleware Doconut з токеном у рядку запиту. Те, що робить middleware, залежить від запиту:

ЗапитПризначення
?token=…&page=NЗображення відрендереної сторінки (PNG)
?token=…&page=N&thumb=1Мініатюра
?token=…&zoom=…Рендеринг збільшеної сторінки
?token=…&search=termПовнотекстовий пошук (з ліцензійним контролем)
?token=…&bookmarksСтруктура/закладки документа
?token=…&copy / &showlinks / &fileFormatКопіювання тексту, гіперпосилання та інформація про формат
?token=…&metaТехнічні метадані DICOM; повертає 501 для DICOM‑сесії у цьому пакеті
?token=…&action=rotate/flip/closeДії над сторінкою та явне закриття
?token=…&AnnSave=… / &AnnLoadЗбереження/завантаження анотацій

Кожен з цих шляхів спочатку проходить валідацію:

  • Відсутній токен → middleware повертає 404 (або банер версії, коли ShowDoconutInfo = true).
  • Невідомий або прострочений токен → зображення помилки з текстом Сесію документа не знайдено. Будь ласка, відкрийте документ знову.
  • Відсутній middleware сесії (при UnsafeMode = false) → HTTP 500 з повідомленням Middleware сесії не налаштовано. Викличте UseSession() перед UseDoconut().
  • Токен відкрито іншим браузерним сеансом → зображення помилки з текстом Ви не маєте дозволу переглядати цю сторінку.

Де монтується middleware

UseDoconut() відповідає на запити, що містять токен, незалежно від того, де ви його монтуєте. Довідковий застосунок зберігає історичну форму запиту DocImage.axd у гілці MapWhen, тому існуючий клієнт продовжує викликати той самий URL. Яким би ви не обрали, BasePath клієнта має відповідати йому — див. ViewerConfig.

Обслуговування сторінок з спільного сховища замість вузла відкриття — це зовсім інша схема; див. Distributed Deployments.

Закриття документа

csharp
viewer.CloseDocument(token);

CloseDocument видаляє сесію з кешу (що звільняє підлеглий движок документа та одразу звільняє пам'ять), стирає маркер secure-{token} і відкликає доступ. Викликати його необов’язково — ковзний термін дії робить те ж саме автоматично — але для великих документів це ввічливий спосіб звільнити пам’ять одразу після завершення користувачем.

Він викликається на інжектованому Viewer. Попередній підхід — створювати короткоживущий Viewer у блоці using лише для закриття токену — не має еквіваленту і не потрібен.

Висновки

  • Один відкритий документ = одна сесія = один токен. Токени прив’язані до браузерної сесії, а не до глобальних URL.
  • Токен закінчує термін дії у ковзному вікні; переглядач, який залишився без активності понад DocOptions.TimeOut, потребує повторного відкриття.
  • Viewer можна інжектувати та вільно ділитися; сесії містять весь стан.

Чи була ця сторінка корисною?