Jak działa Viewer

Cykl życia żądania dokumentu

Doconut renderuje dokumenty jako obrazy podzielone na strony, serwowane przez middleware ASP.NET Core. Zrozumienie cyklu życia — otwarcie, token, żądania stron, zamknięcie — wyjaśnia prawie każde zachowanie, które zaobserwujesz, włącznie z komunikatami o błędach.

Trzy elementy składowe

  • Viewer — publiczna usługa, którą wstrzykujesz. Otwiera dokumenty i zwraca tokeny sesji.
  • Sesja dokumentu — obiekt po stronie serwera przechowujący załadowany dokument, indeksowany tokenem w IMemoryCache.
  • Middleware Doconut — dodany przez UseDoconut(); odpowiada na każde żądanie wysyłane przez widget przeglądarki (pages, thumbnails, search, annotations, …), zawsze uwierzytelnione tokenem.

Viewer jest bezstanowy — z założenia

Viewer jest zamknięty (sealed), nie przechowuje żadnego stanu dokumentu per żądanie i celowo nie implementuje IDisposable. Sesje istnieją niezależnie w menedżerze sesji i są czyszczone przez wygaśnięcie pamięci podręcznej lub wywołanie CloseDocument(token).

Nie tworzysz go już ręcznie. AddDoconut() rejestruje go jako usługę przejściową; wstrzykuj go tam, gdzie jest potrzebny:

csharp
app.MapPost("/api/open", async (string fileName, Viewer viewer) =>
{
    var token = await viewer.OpenDocumentAsync($"files/{fileName}");
    return Results.Content(token, "text/plain");
});

W aplikacji MVC przyjmij go jako parametr konstruktora; w widoku Razor użyj @inject Doconut.Viewer Viewer. Pamięci podręczne aplikacji przechowujące instancje Viewer nie są już potrzebne — i nie są już poprawne, ponieważ nie przechowują niczego wartego buforowania.

Co się dzieje wewnątrz OpenDocumentAsync

  1. Bramka licencyjna. Odrzucona lub przeterminowana licencja (czarna lista, zmodyfikowana lub kompilacja poza oknem aktualizacji licencji) natychmiast rzuca LicenseException z powodem odrzucenia jako komunikatem — otwieranie nigdy nie degraduje cicho przy nieprawidłowej (w przeciwieństwie do nieobecnej) licencji. Licencja tymczasowa lub subskrypcyjna, której termin kalendarzowy wygasł, jest wyjątkiem: nie rzuca wyjątku — degraduje do znaku wodnego.
  2. Tworzenie sesji. Fabryka viewerów wybiera odpowiedni viewer formatu dla rozszerzenia pliku i ładuje dokument (zobacz Rendering Pipeline). Sesja jest przechowywana w IMemoryCache pod nowym tokenem GUID z przesuwanym wygaśnięciem — DocOptions.TimeOut minut, domyślnie 60. Każde żądanie strony resetuje licznik.
  3. Rejestracja zabezpieczeń. Przy UnsafeMode = false (wartość domyślna), token jest powiązany z sesją ASP.NET wywołującego: w sesji zapisywany jest znacznik secure-{token}, więc tylko sesja przeglądarki, która otworzyła dokument, może żądać jego stron.
  4. Token jest zwracany. Jest jedynym poświadczeniem dla wszystkiego, co następuje.

Nie ma osobnego kroku rozgrzewki. Poprzednia biblioteka udostępniała InitCache() w tym celu; już nie istnieje i nic go nie zastępuje.

Trzy przeciążenia różnią się jedynie wejściem: ścieżka do pliku, ścieżka do pliku plus konfiguracja per format (PdfConfig, WordConfig, …) lub Stream plus FileInfo, którego rozszerzenie określa format.

Jak widget pobiera strony

Widget kliencki wywołuje middleware Doconut z tokenem w ciągu zapytania. To, co robi middleware, zależy od żądania:

ZapytanieCel
?token=…&page=NWygenerowany obraz strony (PNG)
?token=…&page=N&thumb=1Miniatura
?token=…&zoom=…Renderowanie powiększonej strony
?token=…&search=termWyszukiwanie pełnotekstowe (z bramką licencyjną)
?token=…&bookmarksSpis treści/dodruki dokumentu
?token=…&copy / &showlinks / &fileFormatKopiowanie tekstu, hiperłącza i informacje o formacie
?token=…&metaMetadane techniczne DICOM; zwraca 501 dla sesji DICOM w tym pakiecie
?token=…&action=rotate/flip/closeAkcje na stronie i wyraźne zamknięcie
?token=…&AnnSave=… / &AnnLoadZapis/odczyt adnotacji

Każda z tych ścieżek najpierw podlega walidacji:

  • Brak tokenu → middleware zwraca 404 (lub baner wersji, gdy ShowDoconutInfo = true).
  • Nieznany lub wygasły token → obraz błędu z komunikatem Document session not found. Please re-open document.
  • Brak middleware sesji (przy UnsafeMode = false) → HTTP 500 z komunikatem Session middleware not configured. Call UseSession() before UseDoconut().
  • Token otwarty w innej sesji przeglądarki → obraz błędu z komunikatem You Are Not Authorized To View This Page.

Gdzie montowany jest middleware

UseDoconut() odpowiada na żądania zawierające token, niezależnie od miejsca montażu. Aplikacja referencyjna zachowuje historyczną strukturę żądania DocImage.axd na gałęzi MapWhen, więc istniejący klient nadal wywołuje ten sam URL. Niezależnie od wyboru, BasePath klienta musi się z nim zgadzać — zobacz ViewerConfig.

Serwowanie stron z współdzielonego magazynu zamiast z węzła otwierającego to zupełnie inny układ; zobacz Rozproszone wdrożenia.

Zamykanie dokumentu

csharp
viewer.CloseDocument(token);

CloseDocument usuwa sesję z pamięci podręcznej (co zwalnia podlegający silnik dokumentu i natychmiast zwalnia jego pamięć), usuwa znacznik secure-{token} i cofa przyznany dostęp. Wywołanie jest opcjonalne — przesuwane wygaśnięcie wykonuje tę samą automatyczną czyszczenie — ale dla dużych dokumentów jest to uprzejmy sposób zwolnienia pamięci w momencie, gdy użytkownik skończył.

Jest wywoływane na wstrzykniętym Viewer. Poprzedni wzorzec — tworzenie krótkotrwałego Viewer w bloku using wyłącznie po to, by zamknąć token — nie ma odpowiednika i nie jest potrzebny.

Najważniejsze wnioski

  • Jeden otwarty dokument = jedna sesja = jeden token. Tokeny są powiązane z sesją przeglądarki, nie są globalnymi URL‑ami.
  • Token wygasa w przesuwanym oknie; viewer pozostawiony bezczynny dłużej niż DocOptions.TimeOut wymaga ponownego otwarcia.
  • Viewer może być wstrzykiwany i współdzielony dowolnie; sesje przenoszą cały stan.

Czy ta strona była pomocna?