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 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).

Wstrzyknij 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");
});

Co się dzieje wewnątrz OpenDocumentAsync

  1. Brama licencyjna. Odrzucona lub wygasła wersja licencji (czarna lista, sfałszowana lub kompilacja poza oknem aktualizacji licencji) natychmiast rzuca LicenseException, z powodem odrzucenia jako komunikatem — otwieranie nigdy nie przechodzi cicho w tryb degradacji przy nieprawidłowej (w przeciwieństwie do brakującej) licencji. Wyjątkiem jest tymczasowa lub subskrypcyjna licencja wygasła kalendarzowo: nie rzuca wyjątku — przechodzi w tryb 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 świeżym tokenem GUID z wygaśnięciem przesuwanymDocOptions.TimeOut minut, domyślnie 60. Każde żądanie strony resetuje licznik.
  3. Rejestracja zabezpieczeń. Przy UnsafeMode = false (domyślnie), token jest powiązany z sesją ASP.NET wywołującego: marker secure-{token} jest zapisywany w sesji, tak że 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.

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 wykrywanie formatu.

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 strony z powiększeniem
?token=…&search=termWyszukiwanie pełnotekstowe (z bramą licencyjną)
?token=…&bookmarksSpis treści/dodruki dokumentu
?token=…&copy / &showlinks / &fileFormat / &metaKopiowanie tekstu, hiperłącza, informacje o formacie, techniczne metadane DICOM
?token=…&action=rotate/flip/closeAkcje na stronie i wyraźne zamknięcie
?token=…&AnnSave=… / &AnnLoadZapis/odczyt adnotacji

Każda z tych ścieżek najpierw jest walidowana:

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

Zamykanie dokumentu

csharp
viewer.CloseDocument(token);

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

Najważniejsze wnioski

  • Jedno otwarte dokument = jedna sesja = jeden token. Tokeny są powiązane z sesją przeglądarki, nie są globalnymi URL‑ami.
  • Token wygasa w oknie przesuwanym; viewer pozostawiony bezczynny po upływie 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?