Швидкий старт

Відобразіть ваш перший документ за кілька хвилин

Цей посібник переводить додаток ASP.NET Core від порожнього Program.cs до документа, що відображається в браузері: реєстрація сервера, повний пакет Viewer (панель інструментів Viewer, монтування Viewer та необов’язкові стрічки Пошуку/Анотацій), посилання на ресурси, ініціалізація клієнта, відкриття документа та виконання.

Налаштування сервера

AddDoconut() реєструє служби; UseDoconutResources() та UseDoconut() підключають проміжне програмне забезпечення. Виклик ресурсів має бути першим. Виклики сесії також потрібні — стандартна безпека документів Doconut перевіряє кожен запит сторінки проти стану сесії ASP.NET. Уже зареєстровано Doconut під час Встановлення? Перейдіть до наступного розділу.

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
});
builder.Services.AddSession(); // Doconut document security rides on ASP.NET session state

app.UseSession();          // call UseSession() before UseDoconut()
app.UseDoconutResources(); // must be registered before UseDoconut()
app.UseDoconut();

Для розташування у стилі продакшн, прив’яжіть проміжне програмне забезпечення до явної гілки та тримайте чотири налаштування шляхів узгодженими:

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = Path.Combine(AppContext.BaseDirectory, "Doconut.Viewer.lic");
    options.MiddlewarePath = "/doconut";
    options.ResourcesPath = "/doconut-res";
    options.UnsafeMode = false;
});
builder.Services.AddSession();

app.UseRouting();
app.UseSession();
app.UseDoconutResources();
app.Map("/doconut", branch => branch.UseDoconut());

MiddlewarePath — це координуюче значення; воно саме по собі не створює гілку ASP.NET Core. У цьому прикладі хост прив’язує /doconut, тому клієнт має використовувати BasePath: '/doconut'. ResourcesPath подає вбудований пакет за адресою /doconut-res, а шлях до ресурсів зображень віджету становить ResPath: '/doconut-res/images'.

Додайте переглядач на сторінку

Viewer — це обов’язковий ядро сторінки. Його поверхня рендерингу використовує два вкладені div:

html
<div id="divDocViewer">
    <div id="div_ctlDoc"></div>
</div>

Розглядайте панель інструментів, монтування модулів та поверхню Viewer як одну композицію сторінки. Пошук і Анотації вбудовують свої стрічки у необов’язкові монтування, але ці модулі ніколи не працюють окремо: вони завжди приєднуються до Viewer на тій самій сторінці. Використовуйте той самий порядок, що й у Doconut.TestApp та Doconut.TestApp.Distributed:

html
<nav id="toolbar" aria-label="Document viewer controls">
    <!-- Viewer navigation, zoom, Search, and Annotation buttons -->
</nav>

<div id="searchBarMount"></div>
<div id="annBarMount"></div>

<div id="divDocViewer">
    <div id="div_ctlDoc"></div>
</div>

Посилання на ресурси переглядача

У Razor‑виді ін’єкована служба Viewer генерує теги <link> та <script> переглядача у правильному порядку — віджет є jQuery‑плагіном, тому jQuery має бути завантажений до скриптів переглядача:

html
@inject Doconut.Viewer Viewer

@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
    IncludeBootstrapCss = true,
    IncludeViewerCss    = true
}))

@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
    IncludeJQuery        = true,
    IncludeBootstrap     = true,
    IncludeViewerScripts = true
}))

Для повного пакету Viewer запитуйте ресурси переглядача та модулів одночасно:

html
@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
    IncludeBootstrapCss  = true,
    IncludeViewerCss     = true,
    IncludeSearchCss     = true,
    IncludeAnnotationCss = true
}))

@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
    IncludeJQuery             = true,
    IncludeBootstrap         = true,
    IncludeViewerScripts     = true,
    IncludeSearchScripts     = true,
    IncludeSearchBar         = true,
    IncludeAnnotationScripts = true,
    IncludeAnnotationBar     = true
}))

IncludeViewerCss і IncludeViewerScripts — обов’язкові базові прапорці. Ніколи не публікуйте приклад стрічки Пошуку або Анотацій без них, без монтування Viewer та без екземпляра docViewer. ReferenceCss і ReferenceScripts пропускають ресурси необов’язкового модуля, коли поточна ліцензія не надає таку можливість; ядро Viewer все одно запускається.

Ініціалізація переглядача

Клієнтський віджет — це jQuery‑плагін. Ось мінімальний набір реальних параметрів ініціалізації (не псевдокод):

javascript
let searchBar = null;
let annBar = null;

const objViewer = $('#div_ctlDoc').docViewer({
    showThumbs: true,
    autoLoad:   false,
    pageZoom:   100,
    FitType:    'width',
    BasePath:   '/doconut',
    ResPath:    '/doconut-res/images',
    onViewerReady: function () {
        // pages are visible; safe to hide a loading spinner here
    },
    // Forward annotation lifecycle events to the embedded ribbon when it is present.
    onAnnLoaded:    () => annBar?.handleAnnLoaded(),
    onAnnSaved:     () => annBar?.handleAnnSaved(),
    onAnnSaveError: () => annBar?.handleAnnSaveError(),
    onAnnClosed:    () => annBar?.handleAnnClosed(),
    onError: function (message) {
        console.error('Doconut viewer error:', message);
    }
});

Кейсинг параметрів дійсно змішаний — showThumbs, autoLoad і pageZoom написані у camelCase, а FitType, BasePath і ResPath — у PascalCase. Єдина послідовність відсутня; помилковий регістр призведе до тихого ігнорування параметра (віджет повернеться до значення за замовчуванням замість помилки).

Збірка повного пакету Viewer

Обидва приклади .NET 6 встановлюють наступні частини разом на одній сторінці:

Частина пакетуВимогаЯк підключається
Ресурси Viewer, монтування та objViewerОбов’язковоЯдро рендерингу документа
Панель інструментів ViewerОбов’язково у референсній композиціїМаркування хоста; кнопки викликають той самий objViewer
Стрічка ПошукуНеобов’язковий, ліцензований модульdoconutSearchBar(...).attach(objViewer)
Стрічка АнотаційНеобов’язковий, ліцензований модульdoconutAnnotationBar(...).attach(objViewer)

Хоча головна панель інструментів Viewer — це маркування хоста, вона встановлюється разом із Viewer і ніколи не повинна документуватись як окремий контроль. Це дозволяє тримати її розташування, підписи, іконки та правила авторизації під контролем вашого застосунку, тоді як кожна кнопка керує одним і тим же екземпляром Viewer:

html
<nav id="toolbar" aria-label="Document viewer controls">
    <button type="button" onclick="objViewer.GotoPage(1)">First</button>
    <button type="button" onclick="objViewer.Next(false)">Previous</button>
    <button type="button" onclick="objViewer.Next(true)">Next</button>
    <button type="button" onclick="objViewer.GotoPage(objViewer.TotalPages())">Last</button>
    <button type="button" onclick="objViewer.Zoom(false)">Zoom out</button>
    <button type="button" onclick="objViewer.Zoom(true)">Zoom in</button>
    <button type="button" onclick="objViewer.FitType('width')">Fit width</button>
    <button type="button" onclick="objViewer.FitType('height')">Fit height</button>
    <button type="button" id="openSearch">Search</button>
    <button type="button" id="openAnnotations">Annotations</button>
</nav>

Повна референсна панель також копіює wwwroot/js/viewerToolbar.js у хост‑застосунок для допоміжних функцій обертання, мініатюр, друку, повноекранного режиму, макету та стану кнопок. Завантажте цей файл хоста після Viewer.ReferenceScripts(...). Тримайте допоміжний скрипт і його розмітку <nav id="toolbar"> разом, коли копіюєте повну демонстраційну реалізацію.

Дотримуйтесь порядку ініціалізації пакету, який використовується в обох референсних застосунках:

  1. Вивести CSS для Viewer та ліцензованих модулів.
  2. Відрендерити панель інструментів Viewer, монтування Пошуку/Анотацій та монтування Viewer разом.
  3. Вивести скрипти для Viewer та ліцензованих модулів.
  4. Завантажити viewerToolbar.js хост‑застосунку.
  5. Ініціалізувати docViewer і зберегти отриманий objViewer.
  6. Ініціалізувати кожну ліцензовану стрічку Пошуку або Анотацій.
  7. Викликати attach(objViewer) для кожної стрічки.
  8. Відкрити документ і зберегти його токен для запитів Viewer та модулів.

Doconut.TestApp.Distributed зберігає саме таку композицію UI і той самий допоміжний скрипт панелі інструментів. Його додаткове значення запиту access та налаштування повторних спроб асинхронного рендерингу належать до розподіленого транспорту; вони не змінюють спосіб складання Viewer, панелі інструментів або стрічок.

Серверні захисти важливі: коли необов’язкова можливість недоступна, її скрипт не виводиться, тому функція jQuery‑плагіна не існує.

html
<script>
    let currentToken = '';

    const refitViewer = () =>
        requestAnimationFrame(() => objViewer.Refit());

    @if (Viewer.IsSearchEnabled)
    {
        <text>
    searchBar = $('#searchBarMount').doconutSearchBar({
        docId: 'ctlDoc',
        getRequestParams: () => ({ token: currentToken }),
        onLayout: refitViewer
    });
    searchBar.attach(objViewer);
        </text>
    }

    @if (Viewer.IsAnnotationEnabled)
    {
        <text>
    annBar = $('#annBarMount').doconutAnnotationBar({
        docId: 'ctlDoc',
        getRequestParams: () => ({ token: currentToken }),
        onLayout: refitViewer
    });
    annBar.attach(objViewer);
        </text>
    }

    document.getElementById('openSearch').addEventListener('click', () => {
        if (!searchBar) return;
        searchBar.isOpen() ? searchBar.close() : searchBar.open();
    });

    document.getElementById('openAnnotations').addEventListener('click', () => {
        if (!annBar) return;
        annBar.isOpen() ? annBar.close() : annBar.open();
    });
</script>

Обидва вбудованих компоненти генерують власний DOM‑стрічки. Пошук містить групи Find, Options та Results. Анотації містять інструменти створення, елементи керування стилем, дії збереження та необов’язкові дії експорту/зображення. Барі надають методи open(), close(), reset() і isOpen(); завжди викликайте attach(objViewer) один раз після їх створення.

У наведеному вище прикладі пропущено необов’язкові зворотні виклики хоста та кінцеві точки експорту/зображення Анотацій, щоб мінімізувати старт. Дивіться Пошук та Анотації для повної налаштування функціоналу, або Користувацькі теми для стилізації або заміни панелі інструментів Viewer, якою керує хост.

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

На сервері лише один кінцевий пункт: ін’єкована служба Viewer відкриває документ і повертає токен сесії.

csharp
app.MapPost("/api/open", async (Viewer viewer) =>
{
    // The token is opaque — hand it to the widget, never log or persist it.
    string token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
    return Results.Ok(new { token });
});

Клієнт отримує цей токен і передає його віджету за допомогою objViewer.View(token):

javascript
fetch('/api/open', { method: 'POST' })
    .then(resp => resp.json())
    .then(data => {
        currentToken = data.token;
        objViewer.View(currentToken);
    });

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

Викличте objViewer.Close(), коли користувач залишає переглядач або відкриває інший документ. У серверних робочих процесах viewer.CloseDocument(token) одразу видаляє кешовану сесію, звільняє рендеринговий движок, стирає маркер безпеки та анулює токен. Поступове закінчення терміну дії також виконує таке очищення, проте явне закриття рекомендується для великих документів.

Повний потік запитів виглядає так:

text
AddDoconut + middleware
    -> render CSS/scripts and mount div
    -> initialize docViewer
    -> OpenDocumentAsync
    -> return opaque token
    -> objViewer.View(token)
    -> page/search/annotation requests
    -> Close / CloseDocument

Ставте токен у ролі облікового даних: ніколи не журналюйте його, не зберігайте, передавайте лише віджету. Він ідентифікує активну сесію документа на сервері і перестає працювати, коли сесія закінчується — відкрийте документ знову, щоб отримати новий токен.

Запуск

Помістіть PDF у wwwroot/files/Sample.pdf, запустіть dotnet run і відкрийте сторінку, що містить віджет. Перша сторінка відобразиться у переглядачі з панеллю мініатюр ліворуч. Якщо цього не сталося, дивіться Усунення проблем.

Що ви отримуєте без ліцензії

Відсутність ліцензії не викликає помилку. Переглядач працює звичайно, проте кожна сторінка містить водяний знак оцінки. Дивіться Налаштування ліцензії для того, як Doconut знаходить ліцензію і які зміни відбуваються після її виявлення.

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