Як працює Viewer
Життєвий цикл запиту документа
Doconut рендерить документи як розбиті на сторінки зображення, що подаються через middleware ASP.NET Core. Розуміння життєвого циклу — відкриття, токен, запити сторінок, закриття — пояснює майже всю поведінку, яку ви спостерігатимете, включаючи повідомлення про помилки.
Три складові частини
Viewer— публічний сервіс, який ви інжектуєте. Він відкриває документи та повертає токени сесії.- Сесія документа — об’єкт на боці сервера, що зберігає завантажений документ, індексований токеном у
IMemoryCache. - Middleware Doconut — додається за допомогою
UseDoconut(); відповідає на кожен запит, який робить віджет браузера (pages,thumbnails,search,annotations, …), завжди автентифікований токеном.
Viewer без стану — за задумом
Viewer є sealed, не зберігає стан документа для кожного запиту і навмисно не реалізує IDisposable. Сесії існують незалежно в менеджері сесій і очищуються внаслідок закінчення терміну дії кешу або явного виклику CloseDocument(token).
Інжектуйте його там, де потрібно:
app.MapPost("/api/open", async (string fileName, Viewer viewer) =>
{
var token = await viewer.OpenDocumentAsync($"files/{fileName}");
return Results.Content(token, "text/plain");
});Що відбувається всередині OpenDocumentAsync
- Ліцензійна перевірка. Відхилена або прострочена версія ліцензії (чорний список, підроблена або збірка поза вікном оновлення ліцензії) миттєво генерує
LicenseExceptionз причиною відхилення у повідомленні — відкриття ніколи не деградує без повідомлення для недійсної (на відміну від відсутньої) ліцензії. Ліцензія типу Temporary або підписки, прострочена за календарем, є винятком: вона не генерує виключення — переходить у водяний знак. - Створення сесії. Фабрика переглядачів вибирає відповідний переглядач формату за розширенням файлу та завантажує документ (див. Rendering Pipeline). Сесія зберігається в
IMemoryCacheпід новим GUID токеном з ковзним терміном дії —DocOptions.TimeOutхвилин, за замовчуванням 60. Кожен запит сторінки скидає таймер. - Реєстрація безпеки. При
UnsafeMode = false(за замовчуванням) токен прив'язується до ASP.NET сесії виклику: маркерsecure-{token}записується в сесію, тому лише браузерна сесія, яка відкрила документ, може запитувати його сторінки. - Токен повертається. Це єдина облікова дані для всього подальшого.
Три перевантаження відрізняються лише вхідними параметрами: шлях до файлу, шлях до файлу плюс конфігурація формату (PdfConfig, WordConfig, …) або Stream плюс FileInfo, розширення якого визначає формат.
Як віджет отримує сторінки
Віджет клієнта викликає middleware Doconut з токеном у рядку запиту. Те, що робить middleware, залежить від запиту:
| Запит | Призначення |
|---|---|
?token=…&page=N | Зображення відрендереної сторінки (PNG) |
?token=…&page=N&thumb=1 | Мініатюра |
?token=…&zoom=… | Рендеринг збільшеної сторінки |
?token=…&search=term | Повнотекстовий пошук (з ліцензійною перевіркою) |
?token=…&bookmarks | Структура/закладки документа |
?token=…© / &showlinks / &fileFormat | Копіювання тексту, гіперпосилання та інформація про формат |
?token=…&meta | Технічні метадані DICOM; повертає 501 для DICOM сесії на .NET 6 |
?token=…&action=rotate/flip/close | Дії зі сторінкою та явне закриття |
?token=…&AnnSave=… / &AnnLoad | Збереження/завантаження анотацій |
Кожен з цих шляхів спочатку проходить валідацію:
- Відсутній токен → middleware повертає 404 (або банер версії, коли
ShowDoconutInfo = true). - Невідомий або прострочений токен → зображення помилки з текстом
Document session not found. Please re-open document. - Відсутній middleware сесії (при
UnsafeMode = false) → HTTP 500 з повідомленнямSession middleware not configured. Call UseSession() before UseDoconut(). - Токен відкритий іншим браузерним сеансом → зображення помилки з текстом
You Are Not Authorized To View This Page.
Закриття документа
viewer.CloseDocument(token);CloseDocument видаляє сесію з кешу (що звільняє підлеглий движок документа і одразу звільняє пам'ять), видаляє маркер secure-{token} і відкликає доступ. Викликати його необов'язково — ковзний термін дії автоматично виконує те ж очищення — але для великих документів це ввічливий спосіб звільнити пам'ять одразу після завершення користувачем.
Основні висновки
- Один відкритий документ = одна сесія = один токен. Токени прив'язані до браузерної сесії, а не до глобальних URL.
- Токен прострочується за ковзним вікном; переглядач, який залишився без активності понад
DocOptions.TimeOut, потребує повторного відкриття. Viewerможна інжектувати та вільно ділитися; сесії містять весь стан.
Чи була ця сторінка корисною?