Πώς Λειτουργεί ο Προβολέας

Ο κύκλος ζωής του αιτήματος εγγράφου

Doconut αποδίδει έγγραφα ως σελιδοποιημένες εικόνες, που εξυπηρετούνται από έναν HTTP handler που καταχωρεί το Web.config σας. Η κατανόηση του κύκλου ζωής — άνοιγμα, διακριτικό, αιτήματα σελίδων, κλείσιμο — εξηγεί σχεδόν κάθε συμπεριφορά που θα παρατηρήσετε, συμπεριλαμβανομένων των μηνυμάτων σφάλματος.

Τα Κινούμενα Μέρη

  • Viewer — η δημόσια υπηρεσία που λαμβάνετε από το DoconutHost.Services. Ανοίγει έγγραφα και επιστρέφει διακριτικά συνεδρίας.
  • Η συνεδρία του εγγράφου — ένα αντικείμενο στο διακομιστή που κρατά το φορτωμένο έγγραφο, διατηρείται στη μνήμη υπό το διακριτικό του.
  • DocImage.axd — ο Doconut.DocImageHandler που δηλώνεται στο Web.config. Απαντά σε κάθε αίτημα που κάνει το widget του προγράμματος περιήγησης (σελίδες, μικρογραφίες, αναζήτηση, σημειώσεις, …), πάντα προσδιορίζεται από το διακριτικό.
  • /doconut-res/* — το Doconut.DoconutResourceModule, το οποίο εξυπηρετεί τα δικά του scripts, στυλ και εικονίδια του widget.

Το Viewer είναι χωρίς κατάσταση — κατά σχεδιασμό

Viewer δεν διατηρεί κατάσταση εγγράφου ανά αίτημα και δεν υλοποιεί το IDisposable. Οι συνεδρίες ζουν ανεξάρτητα από αυτό και καθαρίζονται με λήξη ή με ρητή κλήση CloseDocument(token). Το System.Web δεν έχει injection κατασκευής, έτσι το λαμβάνετε όπου το χρειάζεστε — συνήθως σε μια ενέργεια ελεγκτή:

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

Τι Συμβαίνει μέσα στο OpenDocumentAsync

  1. Πύλη άδειας. Μια απορριφθείσα άδεια (παραποιημένη, σε μαύρη λίστα, ή μια έκδοση εκτός του παραθύρου ενημέρωσης της άδειας) ρίχνει αμέσως LicenseException, με το λόγο ως μήνυμα. Το άνοιγμα δεν υποβαθμίζεται σιωπηρά για μια μη έγκυρη άδεια· μια ελλιπής άδεια μόνο προσθέτει υδατογραφήματα.
  2. Δημιουργία συνεδρίας. Η εργοστασιακή μονάδα του προβολέα επιλέγει τον προβολέα μορφής για την επέκταση του αρχείου και φορτώνει το έγγραφο (δείτε Διαδικασία Απόδοσης). Η συνεδρία αποθηκεύεται στη μνήμη υπό ένα νέο τυχαίο διακριτικό με ολική λήξη με κύλιση των DocOptions.TimeOut λεπτών (προεπιλογή 60). Κάθε αίτημα σελίδας επαναφέρει το ρολόι.
  3. Χορήγηση πρόσβασης. Με UnsafeMode = false (η προεπιλογή), το διακριτικό συνδέεται με την συνεδρία ASP.NET της αίτησης που το άνοιξε: μια καταχώρηση secure-{token} γράφεται σε αυτή τη συνεδρία. Συνεπώς το άνοιγμα πρέπει να εκτελείται σε αίτηση με κατάσταση συνεδρίας — δείτε Συνεδρίες & Ασφάλεια.
  4. Το διακριτικό επιστρέφεται. Είναι το μοναδικό αναγνωριστικό που χρειάζεται το πρόγραμμα περιήγησης για όλα τα επόμενα.

Οι ασύγχρονες υπερφορτώσεις δέχονται διαδρομή αρχείου, διαδρομή αρχείου συν διαμόρφωση ανά μορφή (PdfConfig, WordConfig, …), ή ένα Stream συν ένα FileInfo του οποίου η επέκταση επιλέγει τη μορφή. Για κώδικα πίσω από Web Forms που δεν χρησιμοποιεί ασύγχρονες σελίδες, το OpenDocument προσφέρει τις ίδιες τρεις εισόδους συγχρονικά (μια διαδρομή, ένα stream με όνομα αρχείου, ή έναν πίνακα byte με όνομα αρχείου).

Πώς το widget λαμβάνει σελίδες

Το widget καλεί το DocImage.axd με το διακριτικό στη συμβολοσειρά ερωτήματος. Η ενέργεια του handler εξαρτάται από το αίτημα:

ΕρώτημαΣκοπός
?token=…&page=NΑπόδοση εικόνας σελίδας (PNG)
?token=…&page=N&thumb=1Μικρογραφία
?token=…&zoom=…Απόδοση σελίδας με ζουμ
?token=…&search=termΑναζήτηση πλήρους κειμένου (με πύλη άδειας)
?token=…&bookmarksΔομή εγγράφου και σελιδοδείκτες
?token=…&copy / &showlinks / &fileFormat / &metaΑντιγραφή κειμένου, υπερσυνδέσμους, πληροφορίες μορφής, μεταδεδομένα DICOM
?token=…&action=rotate/flip/closeΕνέργειες σελίδας και ρητό κλείσιμο (POST)
?token=…&AnnSave=… / &AnnLoadΑποθήκευση και φόρτωση σημειώσεων

Κάθε αίτημα ελέγχεται πρώτα:

  • Χωρίς διακριτικό → 404, ή μια σημαία έκδοσης όταν ShowDoconutInfo = true.
  • Το διακριτικό δεν χορηγείται σε αυτή τη συνεδρία ASP.NET → μια εικόνα σφάλματος με κείμενο You Are Not Authorized To View This Page.
  • Άγνωστο ή ληγμένο διακριτικό → μια εικόνα σφάλματος με κείμενο Document session not found. Please re-open document.

Οι εικόνες σφάλματος είναι απλά PNG που αποστέλλονται με κατάσταση 200, ώστε το widget να μπορεί να τις εμφανίσει εκεί που θα ήταν η σελίδα. Μια παρακολούθηση που ελέγχει μόνο τον κωδικό κατάστασης θα τις καταγράψει ως σελίδες που εξυπηρετήθηκαν· μια πραγματική σελίδα είναι δεκάδες έως εκατοντάδες kilobytes, μια εικόνα σφάλματος περίπου 2 KB.

Κλείσιμο εγγράφου

csharp
viewer.CloseDocument(token);

CloseDocument αφαιρεί τη συνεδρία (απελευθερώνοντας τη μηχανή εγγράφου και τη μνήμη της άμεσα), αφαιρεί την καταχώρηση secure-{token} από τη συνεδρία ASP.NET της τρέχουσας αίτησης, και ανακαλεί το διακριτικό. Είναι προαιρετικό — η ολική λήξη με κύλιση κάνει την ίδια εκκαθάριση — αλλά για μεγάλα έγγραφα απελευθερώνει τη μνήμη τη στιγμή που ο χρήστης τελειώνει. Από το πρόγραμμα περιήγησης, το objViewer.Close(true) στέλνει το ισοδύναμο αίτημα κλεισίματος στο DocImage.axd.

Συμπεράσματα

  • Ένα ανοιχτό έγγραφο = μία συνεδρία = ένα διακριτικό, χορηγείται στη συνεδρία ASP.NET που το άνοιξε.
  • Το διακριτικό λήγει σε παράθυρο ολικής λήξης με κύλιση· ένας προβολέας που μένει αδρανής πέρα από το DocOptions.TimeOut χρειάζεται νέο άνοιγμα.
  • Το Viewer μπορεί να ληφθεί και να μοιραστεί ελεύθερα· οι συνεδρίες μεταφέρουν όλη την κατάσταση.

Ήταν αυτή η σελίδα χρήσιμη;