Comment le Viewer fonctionne

Le cycle de vie des requêtes de document

Doconut rend les documents sous forme d'images paginées servies via le middleware ASP.NET Core. Comprendre le cycle de vie — ouverture, jeton, requêtes de pages, fermeture — explique presque tous les comportements que vous observerez, y compris les messages d'erreur.

Les trois parties mobiles

  • Viewer — le service public que vous injectez. Il ouvre les documents et renvoie des jetons de session.
  • La session de document — un objet côté serveur contenant le document chargé, indexé par un jeton dans IMemoryCache.
  • Le middleware Doconut — ajouté par UseDoconut() ; répond à chaque requête que le widget du navigateur effectue (pages, thumbnails, search, annotations, …), toujours authentifié par le jeton.

Viewer est sans état — par conception

Viewer est scellé, ne conserve aucun état de document par requête, et ne met délibérément pas en œuvre IDisposable. Les sessions vivent indépendamment dans le gestionnaire de sessions et sont nettoyées par l'expiration du cache ou par un CloseDocument(token) explicite.

Injectez‑le partout où vous en avez besoin :

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

Ce qui se passe à l'intérieur de OpenDocumentAsync

  1. Portail de licence. Une licence rejetée ou expirée (mise sur liste noire, altérée, ou une version hors de la fenêtre de mise à jour de la licence) lance immédiatement une LicenseException, avec la raison du rejet comme message — l'ouverture ne se dégrade jamais silencieusement pour une licence invalide (par opposition à absente). Une licence temporaire ou d'abonnement expirée au calendrier constitue l'exception : elle ne lance pas d'exception — elle se dégrade en filigrane.
  2. Création de session. La fabrique du viewer sélectionne le bon viewer de format selon l'extension du fichier et charge le document (voir le pipeline de rendu). La session est stockée dans IMemoryCache sous un nouveau jeton GUID avec une expiration glissanteDocOptions.TimeOut minutes, 60 par défaut. Chaque requête de page réinitialise le compteur.
  3. Enregistrement de sécurité. Avec UnsafeMode = false (la valeur par défaut), le jeton est lié à la session ASP.NET de l'appelant : un marqueur secure-{token} est écrit dans la session, de sorte que seule la session du navigateur qui a ouvert le document puisse demander ses pages.
  4. Le jeton est renvoyé. C'est le seul identifiant pour tout ce qui suit.

Les trois surcharges ne diffèrent que par l'entrée : un chemin de fichier, un chemin de fichier plus une configuration par format (PdfConfig, WordConfig, …), ou un Stream plus un FileInfo dont l'extension détermine la détection du format.

Comment le widget obtient les pages

Le widget client appelle le middleware Doconut avec le jeton dans la chaîne de requête. Ce que fait le middleware dépend de la requête :

RequêteObjectif
?token=…&page=NImage de page rendue (PNG)
?token=…&page=N&thumb=1Miniature
?token=…&zoom=…Rendu de page zoomé
?token=…&search=termRecherche en texte intégral (protégée par licence)
?token=…&bookmarksPlan du document / signets
?token=…&copy / &showlinks / &fileFormat / &metaCopie de texte, hyperliens, informations de format, métadonnées techniques DICOM
?token=…&action=rotate/flip/closeActions sur la page et fermeture explicite
?token=…&AnnSave=… / &AnnLoadEnregistrement / chargement des annotations

Chacun de ces chemins est d'abord validé :

  • Pas de jeton → le middleware renvoie 404 (ou une bannière de version lorsque ShowDoconutInfo = true).
  • Jeton inconnu ou expiré → une image d'erreur avec Document session not found. Please re-open document.
  • Middleware de session manquant (avec UnsafeMode = false) → HTTP 500 avec Session middleware not configured. Call UseSession() before UseDoconut().
  • Jeton ouvert par une session de navigateur différente → une image d'erreur avec You Are Not Authorized To View This Page.

Fermeture d'un document

csharp
viewer.CloseDocument(token);

CloseDocument supprime la session du cache (ce qui libère le moteur de document sous‑jacent et libère immédiatement sa mémoire), supprime le marqueur secure-{token}, et révoque l'autorisation d'accès. L'appeler est optionnel — l'expiration glissante effectue le même nettoyage automatiquement — mais pour les gros documents c'est la façon polie de libérer la mémoire dès que l'utilisateur a terminé.

Points clés

  • Un document ouvert = une session = un jeton. Les jetons sont par session de navigateur, pas des URL globales.
  • Le jeton expire selon une fenêtre glissante ; un viewer resté inactif au-delà de DocOptions.TimeOut nécessite une réouverture.
  • Viewer peut être injecté et partagé librement ; les sessions portent tout l'état.

Cette page vous a-t-elle été utile ?