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 możesz zaobserwować, 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, identyfikowany tokenem w IMemoryCache.
  • Middleware Doconut — dodany przez UseDoconut(); odpowiada na każde żądanie, które wysyła 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 explicite wywołanie CloseDocument(token).

Wstrzyknij go wszędzie 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 build poza oknem aktualizacji licencji) natychmiast rzuca LicenseException, z powodem odrzucenia jako komunikatem — otwieranie nigdy nie degraduje się cicho przy nieprawidłowej (w przeciwieństwie do nieobecnej) licencji. Licencja tymczasowa lub subskrypcyjna wygasła kalendarzowo 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 świeżym tokenem GUID z przesuwanym wygaśnięciemDocOptions.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, 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.

Nadpisania różnią się jedynie wejściem: ścieżką do pliku, ścieżką do pliku plus konfiguracją 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 kontrolą licencji)
?token=…&bookmarksStruktura dokumentu/zakładki
?token=…&copy / &showlinks / &fileFormatKopiowanie tekstu, hiperłącza i informacje o formacie
?token=…&metaMetadane techniczne DICOM; zwraca 501 dla sesji DICOM w .NET 6
?token=…&action=rotate/flip/closeAkcje na stronie i wyraźne zamknięcie
?token=…&AnnSave=… / &AnnLoadZapis/odczyt adnotacji

Każda z tych ścieżek najpierw przechodzi walidację:

  • 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.
  • Session middleware missing (with UnsafeMode = false) → HTTP 500 with Session middleware not configured. Call UseSession() before UseDoconut().
  • Token opened by a different browser session → an error image with You Are Not Authorized To View This Page.

Zamknięcie 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 — 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ł.

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 oknie przesuwanym; 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?