
Учебник: Открытие документов с внедрённым Doconut Viewer в .NET 8
Введение
Более старые примеры Doconut могут создавать Viewer напрямую, передавая аргументы кэша, HTTP‑контекста и пути к лицензии. Это не соответствует текущей модели интеграции в .NET 8. AddDoconut() регистрирует Viewer через внедрение зависимостей, и конечные точки приложения получают сервис, а не вызывают конструктор.

Этот учебник следует текущему потоку запросов: регистрация сервисов и middleware, выдача встроенных ресурсов просмотрщика, открытие документа с помощью OpenDocumentAsync, возврат непрозрачного токена сеанса и передача этого токена виджету браузера.
1. Установка и регистрация Doconut
Добавьте пакет .NET 8:
dotnet add package Doconut.NET8
Зарегистрируйте Doconut и сервисы сессий ASP.NET:
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.MiddlewarePath = "/doconut";
options.ResourcesPath = "/doconut-res";
options.UnsafeMode = false;
});
builder.Services.AddSession();
Подключите middleware в требуемом порядке. Middleware ресурсов должен выполняться до конечного middleware документа:
app.UseRouting();
app.UseSession();
app.UseDoconutResources();
app.Map("/doconut", branch => branch.UseDoconut());
MiddlewarePath координирует конфигурацию, но сам по себе не создаёт ветку ASP.NET. Сопоставлённый путь /doconut должен соответствовать BasePath виджета.
2. Добавление поверхности просмотрщика и ресурсов
Браузерный просмотрщик Doconut — это плагин jQuery. На Razor‑странице внедрите Viewer и попросите его вывести теги ресурсов в порядке зависимостей:
@inject Doconut.Viewer Viewer
@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
IncludeViewerCss = true
}))
@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
IncludeJQuery = true,
IncludeViewerScripts = true
}))
<div id="divDocViewer">
<div id="div_ctlDoc"></div>
</div>
Инициализируйте виджет с путями, соответствующими регистрации на сервере:
const objViewer = $('#div_ctlDoc').docViewer({
showThumbs: true,
autoLoad: false,
pageZoom: 100,
FitType: 'width',
BasePath: '/doconut',
ResPath: '/doconut-res/images',
onError: function (message) {
console.error('Doconut viewer error:', message);
}
});
Регистрозависимость параметров имеет значение. Используйте имена, показанные установленной версией, вместо их приведения к единому стилю.
3. Внедрение Viewer и открытие документа
Viewer зарегистрирован как transient‑service. Получайте его через внедрение в конечную точку, конструктор или аналогичный механизм в вашем приложении ASP.NET Core.
app.MapPost("/api/open", async (
Viewer viewer,
CancellationToken ct) =>
{
string token = await viewer.OpenDocumentAsync(
"wwwroot/files/Sample.pdf",
ct: ct);
return Results.Ok(new { token });
});
Для загрузки предоставьте поток и FileInfo, расширение которого определяет исходный формат:
app.MapPost("/api/open-upload", async (
IFormFile file,
Viewer viewer,
CancellationToken ct) =>
{
await using var stream = file.OpenReadStream();
string token = await viewer.OpenDocumentAsync(
stream,
new FileInfo(file.FileName),
ct: ct);
return Results.Ok(new { token });
});
Проверьте размер загрузки, расширение и авторизацию перед открытием пользовательского контента. Не преобразовывайте переданное имя файла в путь на сервере.
4. Передача токена в виджет
Получите токен через эндпоинт открытия и передайте его в objViewer.View:
fetch('/api/open', { method: 'POST' })
.then(response => {
if (!response.ok) throw new Error('The document could not be opened.');
return response.json();
})
.then(data => objViewer.View(data.token))
.catch(error => console.error(error));
Обращайтесь с токеном как с учётными данными для живой сессии документа:
- Не записывайте его в журнал и не сохраняйте.
- Возвращайте его только авторизованному клиенту.
- Не раскрывайте путь к исходному файлу.
- Повторно откройте документ, когда сессия истечёт.
- Закройте сессию, когда документ больше не нужен.
5. Явное закрытие серверных сессий
Клиентский код может вызвать objViewer.Close(), когда пользователь покидает просмотрщик. На сервере также можно явно отозвать известный токен:
app.MapPost("/api/close", (string token, Viewer viewer) =>
{
viewer.CloseDocument(token);
return Results.NoContent();
});
Явное закрытие особенно полезно для больших документов. Истечение сессии остаётся резервным вариантом, а не заменой предсказуемого управления жизненным циклом приложения.
6. Добавление дополнительных модулей только после работы ядра
Поиск и аннотации привязываются к уже инициализированному просмотрщику. Добавляйте их CSS, скрипты, монтирование, проверки лицензий и обратные вызовы жизненного цикла только после успешного завершения базового потока:
AddDoconut + session services
-> UseSession
-> UseDoconutResources
-> mapped UseDoconut branch
-> viewer resources and mount
-> initialize docViewer
-> OpenDocumentAsync
-> objViewer.View(token)
Такой порядок отделяет ошибки рендеринга ядра от конфигурации дополнительных модулей.
Общие ошибки миграции
| Старый или неверный шаблон | Текущее направление .NET 8 |
|---|---|
new Viewer(cache, accessor, licensePath) | Внедрить Viewer после AddDoconut() |
| Статические вызовы загрузки лицензии в коде запроса | Настроить ввод лицензии в AddDoconut() |
Синхронные примеры OpenDocument(...) | Использовать OpenDocumentAsync(...) |
| Внешний или вымышленный CDN просмотрщика | Выдавать встроенные ресурсы через ReferenceCss и ReferenceScripts |
Универсальный JavaScript API init() | Инициализировать $('#div_ctlDoc').docViewer(...) |
| Сохранение токена просмотрщика | Сохраняйте идентификатор документа; токен рассматривайте как временный |
Используйте официальную документацию Doconut и проверяйте примеры в соответствии с установленной версией пакета перед адаптацией их к производственному коду.