Как работает Viewer
Жизненный цикл запросов документа
Doconut рендерит документы в виде постраничных изображений, обслуживаемых через middleware ASP.NET Core. Понимание жизненного цикла — открытие, токен, запросы страниц, закрытие — объясняет почти все наблюдаемые поведения, включая сообщения об ошибках.
Три взаимосвязанных компонента
Viewer— публичный сервис, который вы внедряете. Он открывает документы и возвращает токены сеанса.- Сеанс документа — объект на стороне сервера, хранящий загруженный документ, идентифицируемый токеном в
IMemoryCache. - Middleware Doconut — добавлен
UseDoconut(); отвечает на каждый запрос, который делает виджет браузера (pages,thumbnails,search,annotations, …), всегда аутентифицированный токеном.
Viewer без состояния — по замыслу
Viewer закрыт, не хранит состояние документа per-request и сознательно не реализует 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}, поэтому только браузерный сеанс, открывший документ, может запрашивать его страницы. - Токен возвращается. Это единственное удостоверение для всех последующих действий.
Три перегрузки различаются только входными данными: путь к файлу, путь к файлу плюс конфигурация per-format (PdfConfig, WordConfig, …), или Stream плюс FileInfo, расширение которого определяет формат.
Как виджет получает страницы
Виджет клиента вызывает middleware Doconut, передавая токен в строке запроса. Действия middleware зависят от запроса:
| Query | Purpose |
|---|---|
?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.
- Токен истекает по скользящему окну; если Viewer простоял более
DocOptions.TimeOut, требуется повторное открытие. Viewerможно внедрять и свободно делиться; сеансы несут всё состояние.
Была ли эта страница полезной?