Szybki start
Renderuj swój pierwszy dokument w kilka minut
Ten przewodnik prowadzi aplikację ASP.NET Core od pustego Program.cs do dokumentu renderowanego w przeglądarce: rejestracja serwera, pełny pakiet Viewer (pasek narzędzi Viewer, montaż Viewer oraz opcjonalne wstążki Wyszukiwania/Adnotacji), odwołania do zasobów, inicjalizacja klienta, otwieranie dokumentu i wykonanie.
Konfiguracja serwera
AddDoconut() rejestruje usługi; UseDoconutResources() i UseDoconut() podłączają middleware. Wywołanie zasobów musi być pierwsze. Wywołania sesji są również wymagane — domyślne zabezpieczenie dokumentu Doconut weryfikuje każde żądanie strony względem stanu sesji ASP.NET. Stan sesji wymaga pamięci podręcznej: AddDistributedMemoryCache() zapewnia taką pamięć. Aplikacja MVC lub Razor Pages rejestruje ją automatycznie, ale aplikacja minimal-API nie robi tego, i bez niej aplikacja zatrzymuje się przy uruchamianiu z komunikatem Unable to resolve service for type 'IDistributedCache'. Czy Doconut został już zarejestrowany podczas Instalacja? Przejdź do następnej sekcji.
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
});
builder.Services.AddDistributedMemoryCache(); // stan sesji wymaga pamięci podręcznej (MVC/Razor Pages już dodają jedną)
builder.Services.AddSession(); // zabezpieczenie dokumentu Doconut opiera się na stanie sesji ASP.NET
app.UseSession(); // wywołaj UseSession() przed UseDoconut()
app.UseDoconutResources(); // musi być zarejestrowane przed UseDoconut()
app.UseDoconut();For a production-style path layout, map the document middleware to an explicit branch and keep the four path settings aligned:
builder.Services.AddDoconut(options =>
{
options.LicensePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", "Doconut.Viewer.lic");
options.MiddlewarePath = "/doconut";
options.ResourcesPath = "/doconut-res";
options.UnsafeMode = false;
});
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession();
app.UseRouting();
app.UseSession();
app.UseDoconutResources();
app.Map("/doconut", branch => branch.UseDoconut());MiddlewarePath jest wartością koordynacyjną; nie mapuje ona gałęzi ASP.NET Core samodzielnie. W tym przykładzie host mapuje /doconut, więc klient używa BasePath: 'doconut'. ResourcesPath udostępnia wbudowany pakiet pod /doconut-res, a ścieżka zasobów obrazu widżetu to ResPath: 'doconut-res/images'. Zapisz oba bez początkowego ukośnika: przeglądarka dodaje go samodzielnie, więc '/doconut' zamieniłoby się w //doconut/DocImage.axd, co przeglądarka interpretuje jako żądanie do hosta o nazwie doconut, i przeglądarka zwróci błąd "The viewer handler could not be reached".
Dodaj przeglądarkę do strony
Viewer jest wymaganym rdzeniem strony. Jego powierzchnia renderowania używa dwóch zagnieżdżonych elementów div:
<div id="divDocViewer">
<div id="div_ctlDoc"></div>
</div>Traktuj pasek narzędzi, montowanie modułów i powierzchnię Viewer jako jedną kompozycję strony. Wyszukiwanie i Adnotacje wstrzykują swoje wbudowane wstążki do opcjonalnych montowań, ale te moduły nigdy nie są samodzielne: zawsze przyłączają się do Viewer na tej samej stronie. Użyj tej samej kolejności co Doconut.TestApp i Doconut.TestApp.Distributed:
<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>Odwołanie do zasobów przeglądarki
W widoku Razor, wstrzyknięta usługa Viewer generuje znaczniki <link> i <script> przeglądarki w kolejności zależności — widżet jest wtyczką jQuery, więc jQuery musi być załadowany przed skryptami przeglądarki:
@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
}))Dla pełnego pakietu Viewer, żądaj zasobów Viewer i modułów razem:
@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 i IncludeViewerScripts są obowiązkowymi flagami rdzenia. Nigdy nie publikuj przykładu wstążki Wyszukiwania lub Adnotacji bez nich, montażu Viewer oraz instancji docViewer. ReferenceCss i ReferenceScripts pomijają zasoby opcjonalnego modułu, gdy bieżąca licencja nie przyznaje tej funkcji; podstawowy Viewer nadal się uruchamia.
Inicjalizacja przeglądarki
Widżet po stronie klienta jest wtyczką jQuery. Oto minimalny zestaw rzeczywistych opcji inicjalizacji (nie pseudokod):
let searchBar = null;
let annBar = null;
const objViewer = $('#div_ctlDoc').docViewer({
showThumbs: true,
autoLoad: false,
pageZoom: 100,
FitType: 'width',
BasePath: 'doconut', // brak początkowego '/'
ResPath: 'doconut-res/images', // brak początkowego '/'
onViewerReady: function () {
// strony są widoczne; można ukryć wskaźnik ładowania tutaj
},
// Przekaż zdarzenia cyklu życia adnotacji do osadzonego wstęgi, gdy jest obecna.
onAnnLoaded: () => annBar?.handleAnnLoaded(),
onAnnSaved: () => annBar?.handleAnnSaved(),
onAnnSaveError: () => annBar?.handleAnnSaveError(),
onAnnClosed: () => annBar?.handleAnnClosed(),
onError: function (message) {
console.error('Doconut viewer error:', message);
}
});Wielkość liter w nazwach opcji jest naprawdę mieszana — showThumbs, autoLoad i pageZoom są w stylu camelCase, natomiast FitType, BasePath i ResPath są w stylu PascalCase. Nie ma spójnej reguły; jeśli popełnisz błąd w wielkości liter, opcja zostanie cicho zignorowana (widżet powróci do wartości domyślnej zamiast zgłosić błąd).
Zbuduj kompletny pakiet przeglądarki
Obie aplikacje referencyjne .NET 8 instalują następujące części razem na jednej stronie:
| Część pakietu | Wymaganie | Jak jest podłączona |
|---|---|---|
Zasoby przeglądarki, montowanie i objViewer | Wymagane | Główny renderownik dokumentu |
| Pasek narzędzi przeglądarki | Wymagany w kompozycji referencyjnej | Markup hosta; przyciski wywołują ten sam objViewer |
| Wstęga wyszukiwania | Opcjonalny, moduł licencjonowany | doconutSearchBar(...).attach(objViewer) |
| Wstęga adnotacji | Opcjonalny, moduł licencjonowany | doconutAnnotationBar(...).attach(objViewer) |
Chociaż główny pasek narzędzi przeglądarki jest markupem hosta, jest instalowany razem z przeglądarką i nigdy nie powinien być dokumentowany jako odrębny kontroler. Dzięki temu układ, etykiety, ikony i reguły autoryzacji pozostają pod kontrolą Twojej aplikacji, a każdy przycisk steruje tą samą instancją przeglądarki:
<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>Pełny pasek narzędzi referencyjnych kopiuje również wwwroot/js/viewerToolbar.js do aplikacji hosta w celu obsługi obracania, miniatur, drukowania, pełnego ekranu, układu i pomocników stanu przycisków. Załaduj ten plik hosta po wywołaniu Viewer.ReferenceScripts(...). Zachowaj pomocnika i jego markup <nav id="toolbar"> razem przy kopiowaniu pełnej implementacji demonstracyjnej.
Zachowaj kolejność inicjalizacji pakietu używaną przez obie aplikacje referencyjne:
- Emituj zasoby przeglądarki, wyszukiwania i adnotacji razem.
- Renderuj pasek narzędzi przeglądarki, montowanie wstęg i montowanie przeglądarki razem.
- Zainicjalizuj najpierw
docViewer. - Utwórz każdą licencjonowaną wstęgę i dołącz ją do tego samego
objViewer. - Otwórz dokument i zachowaj jego token do żądań modułu.
Doconut.TestApp.Distributed zachowuje tę dokładną kompozycję UI oraz ten sam pomocnik paska narzędzi przeglądarki. Dodatkowa wartość żądania access oraz ustawienia ponownych prób asynchronicznego renderowania należą do transportu rozproszonego; nie zmieniają one sposobu, w jaki przeglądarka, pasek narzędzi lub wstęgi są składane.
Zabezpieczenia po stronie serwera są ważne: gdy opcjonalna funkcja jest niedostępna, jej skrypt nie jest emitowany, więc jej funkcja wtyczki jQuery nie istnieje.
<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>Oba osadzone komponenty generują własny DOM wstęgi. Wstęga wyszukiwania zawiera grupy Znajdź, Opcje i Wyniki. Wstęga adnotacji zawiera narzędzia do tworzenia, kontrolki stylu, akcje zapisu oraz opcjonalne akcje eksportu/obrazu. Wstęgi udostępniają metody open(), close(), reset() i isOpen(); zawsze wywołuj attach(objViewer) raz po ich utworzeniu.
Powyższy przykład pomija opcjonalne wywołania zwrotne hosta oraz endpointy eksportu/obrazu adnotacji, aby zminimalizować uruchamianie. Zobacz Wyszukiwanie i Adnotacje po pełną konfigurację specyficzną dla funkcji, lub Niestandardowe motywy, aby stylizować lub zastąpić pasek narzędzi przeglądarki zarządzany przez hosta.
Otwórz dokument
Po stronie serwera jest jeden punkt końcowy: wstrzyknięta usługa Viewer otwiera dokument i zwraca token sesji.
app.MapPost("/api/open", async (Viewer viewer) =>
{
// Token jest nieprzezroczysty — przekaż go do widżetu, nigdy nie loguj ani nie zapisuj.
string token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
return Results.Ok(new { token });
});Klient pobiera ten token i przekazuje go do widżetu za pomocą objViewer.View(token):
fetch('/api/open', { method: 'POST' })
.then(resp => resp.json())
.then(data => {
currentToken = data.token;
objViewer.View(currentToken);
});Zamknij dokument
Wywołaj objViewer.Close(), gdy użytkownik opuszcza widżet lub otwiera zastępczy dokument. W przepływach sterowanych po stronie serwera, viewer.CloseDocument(token) natychmiast usuwa buforowaną sesję, zwalnia silnik renderujący, usuwa jego znacznik bezpieczeństwa i unieważnia token. Przesuwające się wygaśnięcie ostatecznie wykonuje tę samą czynność, ale explicite zamknięcie jest zalecane dla dużych dokumentów.
Pełny przepływ żądania wygląda następująco:
AddDoconut + middleware
-> render CSS/scripts and mount div
-> initialize docViewer
-> OpenDocumentAsync
-> return opaque token
-> objViewer.View(token)
-> page/search/annotation requests
-> Close / CloseDocumentTraktuj token jak poświadczenie typu bearer: nigdy go nie loguj, nie zapisuj, przekaż go wyłącznie do widżetu. Identyfikuje on aktywną sesję dokumentu na serwerze i przestaje działać, gdy sesja wygaśnie — ponownie otwórz dokument, aby uzyskać nowy token.
Uruchom
Umieść plik PDF w wwwroot/files/Sample.pdf, uruchom dotnet run i otwórz stronę, na której znajduje się widżet. Pierwsza strona renderuje się w widżecie, z panelem miniatur po lewej. Jeśli tak się nie stanie, zobacz Rozwiązywanie problemów.
Co otrzymujesz bez licencji
Brak licencji nie powoduje wyjątku. Widżet renderuje się normalnie, ale każda strona zawiera znak wodny oceny. Zobacz Konfiguracja licencji, aby dowiedzieć się, jak Doconut znajduje licencję i co się zmienia, gdy ją znajdzie.
Czy ta strona była pomocna?