Как работает Viewer
Жизненный цикл запросов документа
Doconut отображает документы в виде постраничных изображений, обслуживаемых HTTP‑обработчиком, зарегистрированным в вашем Web.config. Понимание жизненного цикла — открытие, токен, запросы страниц, закрытие — объясняет почти все наблюдаемые поведения, включая сообщения об ошибках.
Составные части
Viewer— публичный сервис, который вы получаете изDoconutHost.Services. Он открывает документы и возвращает токены сессий.- Сессия документа — объект на стороне сервера, хранящий загруженный документ, удерживаемый в памяти под своим токеном.
DocImage.axd—Doconut.DocImageHandler, объявленный вWeb.config. Он отвечает на каждый запрос, который делает виджет браузера (страницы, миниатюры, поиск, аннотации и т.д.), всегда идентифицируемый токеном./doconut-res/*—Doconut.DoconutResourceModule, который обслуживает собственные скрипты, стили и иконки виджета.
Viewer без состояния — по замыслу
Viewer не хранит состояние документа для каждого запроса и не реализует IDisposable. Сессии существуют независимо от него и очищаются по истечении срока или явным вызовом CloseDocument(token). В System.Web нет внедрения через конструктор, поэтому получайте его там, где нужен — обычно в действии контроллера:
// POST /ViewerApi/Open?fileName=Sample.pdf
[HttpPost]
public async Task<ActionResult> Open(string fileName)
{
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
var path = Server.MapPath("~/files/" + Path.GetFileName(fileName));
var token = await viewer.OpenDocumentAsync(path);
return Content(token, "text/plain");
}Что происходит внутри OpenDocumentAsync
- Лицензионный шлюз. Отклонённая лицензия (подделанная, в чёрном списке или сборка вне окна обновления лицензии) сразу бросает
LicenseExceptionс причиной в сообщении. Открытие никогда не ухудшается тихо при недействительной лицензии; отсутствующая лицензия лишь добавляет водяной знак. - Создание сессии. Фабрика viewer выбирает просмотрщик формата по расширению файла и загружает документ (см. Конвейер рендеринга). Сессия хранится в памяти под новым случайным токеном с скользящим истечением через
DocOptions.TimeOutминут (по умолчанию 60). Каждый запрос страницы сбрасывает таймер. - Предоставление доступа. При
UnsafeMode = false(по умолчанию) токен привязывается к ASP.NET‑сессии запроса, который его открыл: в эту сессию записывается записьsecure-{token}. Поэтому открытие должно происходить в запросе с состоянием сессии — см. Сессии и безопасность. - Токен возвращается. Это единственный идентификатор, который нужен браузеру для всех последующих действий.
Асинхронные перегрузки принимают путь к файлу, путь к файлу плюс конфигурацию формата (PdfConfig, WordConfig и т.д.), или Stream плюс FileInfo, расширение которого определяет формат. Для кода‑behind Web Forms, не использующего асинхронные страницы, OpenDocument предлагает те же три входа синхронно (путь, поток с именем файла или массив байт с именем файла).
Как виджет получает страницы
Виджет вызывает DocImage.axd с токеном в строке запроса. Действия обработчика зависят от запроса:
| Query | Purpose |
|---|---|
?token=…&page=N | Изображение отрисованной страницы (PNG) |
?token=…&page=N&thumb=1 | Миниатюра |
?token=…&zoom=… | Отрисовка страницы с масштабом |
?token=…&search=term | Полнотекстовый поиск (по лицензии) |
?token=…&bookmarks | Структура документа и закладки |
?token=…© / &showlinks / &fileFormat / &meta | Копирование текста, гиперссылки, информация о формате, метаданные DICOM |
?token=…&action=rotate/flip/close | Действия со страницей и явное закрытие (POST) |
?token=…&AnnSave=… / &AnnLoad | Сохранение и загрузка аннотаций |
Каждый запрос проверяется вначале:
- Отсутствует токен →
404, или баннер версии, когдаShowDoconutInfo = true. - Токен не предоставлен этой ASP.NET‑сессии → изображение ошибки с надписью
You Are Not Authorized To View This Page. - Неизвестный или просроченный токен → изображение ошибки с надписью
Document session not found. Please re-open document.
Изображения ошибок — обычные PNG, отправляемые со статусом 200, чтобы виджет мог показывать их вместо страницы. Мониторинг, проверяющий только код статуса, будет считать их обслуженными страницами; реальная страница весит от десятков до сотен килобайт, изображение ошибки — около 2 КБ.
Закрытие документа
viewer.CloseDocument(token);CloseDocument удаляет сессию (немедленно освобождая движок документа и его память), удаляет запись secure-{token} из текущей ASP.NET‑сессии запроса и аннулирует токен. Это необязательно — скользящее истечение делает то же самое — но для больших документов память освобождается сразу после завершения работы пользователя. Из браузера objViewer.Close(true) отправляет эквивалентный запрос закрытия к DocImage.axd.
Ключевые выводы
- Один открытый документ = одна сессия = один токен, предоставленный ASP.NET‑сессии, которая его открыла.
- Токен истекает по скользящему окну; если viewer простаивает дольше
DocOptions.TimeOut, требуется повторное открытие. Viewerможно получать и свободно делиться; все состояния хранятся в сессиях.
Была ли эта страница полезной?