Comment le visualiseur fonctionne

Le cycle de vie de la requête de document

Doconut rend les documents sous forme d'images paginées, servies par un gestionnaire HTTP que votre Web.config enregistre. 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 pièces mobiles

  • Viewer — le service public que vous résolvez depuis DoconutHost.Services. Il ouvre les documents et renvoie des jetons de session.
  • La session du document — un objet côté serveur contenant le document chargé, conservé en mémoire sous son jeton.
  • DocImage.axd — le Doconut.DocImageHandler déclaré dans Web.config. Il répond à chaque requête que le widget du navigateur effectue (pages, vignettes, recherche, annotations, …), toujours identifié par le jeton.
  • /doconut-res/* — le Doconut.DoconutResourceModule, qui fournit les scripts, styles et icônes propres au widget.

Viewer est sans état — par conception

Viewer ne conserve aucun état de document par requête et n'implémente pas IDisposable. Les sessions vivent indépendamment de lui et sont nettoyées par expiration ou un CloseDocument(token) explicite. System.Web n'a pas d'injection de constructeur, donc résolvez‑le là où vous en avez besoin — typiquement dans une action de contrôleur :

csharp
// POST /ViewerApi/Open?fileName=Sample.pdf
[HttpPost]
public async Task<ActionResult> Open(string fileName)
{
    var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
    var path   = Server.MapPath("~/files/" + Path.GetFileName(fileName));

    var token = await viewer.OpenDocumentAsync(path);
    return Content(token, "text/plain");
}

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

  1. Portail de licence. Une licence rejetée (altérée, sur liste noire, ou une version hors de la fenêtre de mise à jour de la licence) lance immédiatement LicenseException, avec la raison comme message. L'ouverture ne se dégrade jamais silencieusement pour une licence invalide ; une licence manquante ne fait qu'ajouter un filigrane.
  2. Création de session. La fabrique du visualiseur choisit le visualiseur de format selon l'extension du fichier et charge le document (voir Rendering Pipeline). La session est stockée en mémoire sous un nouveau jeton aléatoire avec une expiration glissante de DocOptions.TimeOut minutes (par défaut 60). Chaque requête de page réinitialise le compteur.
  3. Octroi d'accès. Avec UnsafeMode = false (la valeur par défaut), le jeton est lié à la session ASP.NET de la requête qui l'a ouverte : une entrée secure-{token} est écrite dans cette session. L'ouverture doit donc s'exécuter dans une requête avec état de session — voir Sessions & Security.
  4. Le jeton est renvoyé. C'est le seul identifiant dont le navigateur a besoin pour tout ce qui suit.

Les surcharges asynchrones acceptent un chemin de fichier, un chemin de fichier plus une configuration par format (PdfConfig, WordConfig, …), ou un Stream plus un FileInfo dont l'extension sélectionne le format. Pour le code‑behind Web Forms qui n'utilise pas de pages asynchrones, OpenDocument propose les mêmes trois entrées de façon synchrone (un chemin, un flux avec un nom de fichier, ou un tableau d'octets avec un nom de fichier).

Comment le widget obtient les pages

Le widget appelle DocImage.axd avec le jeton dans la chaîne de requête. Ce que fait le gestionnaire dépend de la requête :

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

Chaque requête est d'abord vérifiée :

  • Pas de jeton → 404, ou une bannière de version lorsque ShowDoconutInfo = true.
  • Jeton non accordé à cette session ASP.NET → une image d'erreur affichant You Are Not Authorized To View This Page.
  • Jeton inconnu ou expiré → une image d'erreur affichant Document session not found. Please re-open document.

Les images d'erreur sont des PNG ordinaires envoyés avec le statut 200, de sorte que le widget peut les afficher à la place de la page. Un contrôle de surveillance qui ne regarde que le code d'état les signalera comme des pages servies ; une vraie page fait plusieurs dizaines à centaines de kilooctets, une image d'erreur environ 2 KB.

Fermer un document

csharp
viewer.CloseDocument(token);

CloseDocument supprime la session (libérant immédiatement le moteur de document et sa mémoire), supprime l'entrée secure-{token} de la session ASP.NET de la requête en cours, et révoque le jeton. C'est optionnel — l'expiration glissante effectue le même nettoyage — mais pour les gros documents cela libère la mémoire dès que l'utilisateur a fini. Depuis le navigateur, objViewer.Close(true) envoie la requête de fermeture équivalente à DocImage.axd.

Points clés

  • Un document ouvert = une session = un jeton, accordé à la session ASP.NET qui l'a ouvert.
  • Le jeton expire sur une fenêtre glissante ; un visualiseur laissé inactif au-delà de DocOptions.TimeOut nécessite une réouverture.
  • Viewer peut être résolu et partagé librement ; les sessions portent tout l'état.

Cette page était-elle utile ?