Μεταφορά σε .NET Standard 2.1

Μετακινήστε μια υπάρχουσα Doconut.NETStandard εφαρμογή από 26.7.0 σε 26.8.0

Το Doconut διαθέτει δύο ξεχωριστές ενσωματώσεις .NET Standard. Χρησιμοποιούν το ίδιο όνομα πακέτου Doconut.NETStandard, επομένως εντοπίστε τη γενιά από την έκδοση και τα API στην εφαρμογή πριν αλλάξετε πακέτα, εκκίνηση, άδειες ή πόρους του προγράμματος περιήγησης.

Η έκδοση είναι το σημείο διακλάδωσης

Και οι δύο γενιές δημοσιεύονται υπό το ίδιο αναγνωριστικό πακέτου. Μόνο η έκδοση τις διακρίνει:

ΈκδοσηΣτόχοςAPI
26.7.0 και κάτωnetstandard2.0το προηγούμενο API
26.8.0 και πάνωnetstandard2.1το τρέχον API

Η αύξηση του αριθμού έκδοσης είναι η αναβάθμιση. Δεν υπάρχει ξεχωριστό πακέτο για εγκατάσταση και δεν υπάρχει shim συμβατότητας — το 26.8.0 είναι διαφορετική επιφάνεια API. Περιμένετε σφάλματα μεταγλώττισης μετά την αύξηση· το υπόλοιπο αυτού του οδηγού είναι η λίστα τους.

Ποια ενσωμάτωση χρησιμοποιείτε;

Αν το έργο περιέχει…Γενιά
new Viewer(_cache, _accessor, ...)Προηγούμενη
viewer.OpenDocument(...) (synchronous)Προηγούμενη
viewer.InitCache()Προηγούμενη
UseDoconut(new DoconutOptions { ... })Προηγούμενη
UseDoconutWebFarm(...) / WebFarmOptionsΠροηγούμενη
Viewer.DoconutLicense(...) or Viewer.SetLicensePlugin(...)Προηγούμενη
viewer.Converter.GetConverter()Προηγούμενη
using Doconut.Configs; / using Doconut.Models;Προηγούμενη
Manually copied docViewer.js, documentLinks.js, or docViewer.UI.jsΠροηγούμενη
builder.Services.AddDoconut(...)Τρέχουσα
app.UseDoconutResources() plus app.UseDoconut() with no argumentsΤρέχουσα
Viewer supplied by dependency injectionΤρέχουσα
await viewer.OpenDocumentAsync(...)Τρέχουσα

Αν και οι δύο στήλες εμφανίζονται στην ίδια εφαρμογή, θεωρήστε τη μετάβαση ως ατελή. Μην στέλνετε ένα διακριτικό εγγράφου μέσω πόρων ή middleware από την άλλη γενιά.

Ελέγξτε πρώτα το πλαίσιο φιλοξενίας

Αυτό είναι ένα σκληρό φράγμα, όχι προτίμηση. Το τρέχον πακέτο στοχεύει στο netstandard2.1:

ΠλαίσιοΜπορεί να καταναλώσει 26.8.0
.NET Core 3.0 ή μεταγενέστερο (συμπεριλαμβανομένων .NET 5/6/7/8)Ναι
.NET Framework, οποιαδήποτε έκδοσηΌχι

Το .NET Framework δεν μπορεί να αναφερθεί σε βιβλιοθήκη netstandard2.1. Εάν η εφαρμογή εκτελείται σε .NET Framework, σταματήστε εδώ και χρησιμοποιήστε το πακέτο Doconut.NETFramework αντ' αυτού· από το 26.9.0 απαιτεί .NET Framework 4.7.2. Και οι δύο εφαρμογές αναφοράς για αυτήν την έκδοση στοχεύουν στο net8.0.

Πριν κάνετε τη μετάβαση

  1. Δημιουργήστε ένα κλαδί και ένα αναπληρωματικό αντίγραφο ασφαλείας της υπάρχουσας εφαρμογής που μπορεί να αναπτυχθεί.
  2. Καταγράψτε τις ακριβείς εκδόσεις των βασικών και των πρόσθετων πακέτων.
  3. Καταγράψτε κάθε κλήση new Viewer(...), κλήση InitCache(), κλήση φόρτωσης άδειας, αντιστοίχηση UseDoconutWebFarm, ελεγκτή μετατροπής, αντιγραμμένο script Doconut, προσαρμοσμένη ενέργεια γραμμής εργαλείων, callback του viewer και το σημείο λήψης ανοίγματος εγγράφου.
  4. Διατηρήστε τα τρέχοντα αρχεία .lic και τα μυστικά ανάπτυξης εκτός ελέγχου πηγαίου κώδικα.
  5. Καταγράψτε ένα αντιπροσωπευτικό σύνολο εγγράφων PDF, Office, εικόνας, CAD, email, DICOM, αναζητήσιμα, προστατευμένα με κωδικό πρόσβασης και σχολιασμένα.
  6. Καταγράψτε το υπάρχον χρονικό όριο συνεδρίας, τη συμπεριφορά ασφαλείας, τις γραμματοσειρές και τις ρυθμίσεις πλατφόρμας.

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

1. Ονοματοχώροι: σχεδόν όλα μεταφέρθηκαν στη ρίζα

Οι τύποι διαμόρφωσης ήταν διασκορπισμένοι σε τέσσερις ονοματοχώρους. Τώρα είναι όλοι στο Doconut.

ΠρινΤώρα
using Doconut.Configs.View;using Doconut;
using Doconut.Models;using Doconut;
using Doconut.Configs;using Doconut;
using Doconut.Configs.Cloud;using Doconut.Clouds;
using Doconut.Configs.Conversion;αμετάβλητο
using Doconut.Middleware;αμετάβλητο

Τα ονόματα τύπων δεν άλλαξαν: WordConfig, PdfConfig, ExcelConfig, CssConfig, ScriptConfig, CloudUploadConfig, AzureConfig, CDNConfig, FileShareConfig και τα υπόλοιπα παραμένουν. Στα περισσότερα αρχεία η πλήρης επεξεργασία είναι η διαγραφή δύο γραμμών using.

Doconut.Configs.Editor (BaseConfigEditor, PdfConfigEditor) αφαιρέθηκε και δεν υπάρχει αντικατάσταση σε αυτό το πακέτο. Εάν η εφαρμογή σας αναφερόταν σε αυτούς τους τύπους, προγραμματίστε αυτό το μέρος ξεχωριστά και μην το θεωρήσετε μέρος αυτής της μετάβασης.

2. Συμβατότητα πακέτου και άδειας

Αντικαταστήστε ή ενημερώστε το βασικό πακέτο σκόπιμα· μην βασίζεστε στο ίδιο αναγνωριστικό πακέτου για την επιλογή του νέου API. Η προεπιλεγμένη εντολή εγκαθιστά την πιο πρόσφατη σταθερή έκδοση:

bash
dotnet add package Doconut.NETStandard

Για μια επαναλήψιμη μετάβαση στην έκδοση που ελέγχεται από αυτόν τον οδηγό, περάστε την έκδοση ως ξεχωριστή επιλογή:

bash
dotnet add package Doconut.NETStandard --version 26.8.0

Διατηρήστε κάθε πρόσθετο Doconut στην ίδια έκδοση με το βασικό πακέτο — Doconut.NETStandard.Converter και Doconut.NETStandard.Dicom. Η τρέχουσα ενσωμάτωση φορτώνει τις άδειες μία φορά κατά τη διάρκεια του AddDoconut(), χρησιμοποιώντας αυτήν την προτεραιότητα:

text
LicenseStream > LicenseContent > LicensePath > automatic discovery

Η αυτόματη ανίχνευση αναζητά αρχεία Doconut.Viewer.lic και τα συνοδευτικά αρχεία Doconut.Viewer.<Capability>.lic. Οι προηγούμενες στατικές κλήσεις Viewer.DoconutLicense(...) και Viewer.SetLicensePlugin(...) δεν αποτελούν τρέχον μηχανισμό εκκίνησης, όπως επίσης δεν είναι η List<string> με διαδρομές αδειών που αποδεχόταν ο παλιός κατασκευαστής Viewer. Μετακινήστε την άδεια στο DoconutOptions, διατηρήστε τα συνοδευτικά αρχεία μαζί όταν χρησιμοποιείτε την αυτόματη ανίχνευση, επανεκκινήστε μετά την αλλαγή μιας άδειας και επαληθεύστε τις δυνατότητες μέσω του IDoconutLicenseService.

Μην υποθέτετε ότι η παρουσία μιας παλιάς άδειας πρόσθετου αποδεικνύει το δικαίωμα για την τρέχουσα έκδοση του πρόσθετου. Δοκιμάστε το Viewer, το Search, το Annotation, το Converter και το DICOM ξεχωριστά με τα εγκεκριμένα αντικείμενα έκδοσης.

3. Εκκίνηση και ενσωμάτωση εξαρτήσεων

Προηγουμένως, το viewer δημιουργούνταν ανά αίτηση και οι επιλογές περνιόνταν στο middleware:

csharp
// Προηγούμενη ενσωμάτωση — μόνο για σύγκριση· μην το μεταγλωττίσετε με το τρέχον SDK.
var viewer = new Viewer(_cache, _accessor);
// …
appBranch.UseDoconut(new DoconutOptions { UnSafeMode = false, ShowDoconutInfo = false });

Η τρέχουσα ενσωμάτωση καταχωρεί το Doconut μία φορά και λαμβάνει το Viewer από την ενσωμάτωση εξαρτήσεων:

csharp
builder.Services.AddDoconut(options =>
{
    options.UnsafeMode      = false;   // σημειώστε την αλλαγή ορθογραφίας: UnSafeMode → UnsafeMode
    options.ShowDoconutInfo = false;
    options.LicensePath     = "Doconut.Viewer.lic";
});
builder.Services.AddDistributedMemoryCache(); // η κατάσταση συνεδρίας χρειάζεται μια κρυφή μνήμη (MVC/Razor Pages ήδη προσθέτουν μία)
builder.Services.AddSession();

app.UseSession();
app.UseDoconutResources();
app.UseDoconut();

Viewer είναι μια μεταβλητή υπηρεσία. Ο διαχειριστής συνεδρίας εγγράφων και η κρυφή μνήμη του διαχειρίζονται την πιο μακροχρόνια κατάσταση του εγγράφου, όχι η συγκεκριμένη ενσωματωμένη παρουσία Viewer.

Τρία πράγματα που πρέπει να μεταφερθούν:

  • new Viewer(cache, accessor) έχει αφαιρεθεί. Ενσωματώστε το Doconut.Viewer στον ελεγκτή σας, ή χρησιμοποιήστε @inject Doconut.Viewer Viewer σε μια Razor προβολή.
  • UseDoconutResources() αντικαθιστά την χειροκίνητη σύνδεση app.UseMiddleware<EmbeddedResourceMiddleware>() και πρέπει να εκτελείται πριν από το κλαδί του εγγράφου.
  • UnSafeMode → UnsafeMode. Μία αλλαγή κατά ένα χαρακτήρα που ο μεταγλωττιστής θα εντοπίσει.

Όταν το UnsafeMode είναι false, το SDK επικυρώνει το διακριτικό συνεδρίας σε σχέση με το αρχικό αίτημα, έτσι το AddSession() / UseSession() πρέπει ακόμη να βρίσκεται στην αλυσίδα, το UseSession() πριν από το κλαδί.

Μέθοδοι που δεν υπάρχουν πλέον

ΠρινΤώρα
viewer.OpenDocument(path, config, options)await viewer.OpenDocumentAsync(path, config, options)
viewer.InitCache()αφαιρέθηκε — δεν υπάρχει τίποτα για χειροκίνητη προθέρμανση· διαγράψτε την κλήση και οποιαδήποτε σημαία "did I already init?" γύρω της
viewer.ExportToPng(sharedPath)see §7
viewer.ExportToCloud(cloudConfig)see §7
using var v = new Viewer(...); v.CloseDocument(t)viewer.CloseDocument(token) on the injected instance

4. Middleware και δρομολόγηση πόρων

UseDoconut() τώρα δεν δέχεται ορίσματα. Η δομή του κλαδιού MapWhen δεν χρειάζεται αλλαγή — μόνο το middleware μέσα σε αυτό:

csharp
app.UseDoconutResources();   // BEFORE the branch

app.MapWhen(
    ctx => ctx.Request.Path.Value?.EndsWith("DocImage.axd", StringComparison.OrdinalIgnoreCase) == true,
    branch => branch.UseDoconut());

Στην τρέχουσα αλυσίδα επεξεργασίας:

  1. καλέστε το UseSession() πριν από το Doconut ενώ η ασφάλεια συνεδρίας είναι ενεργοποιημένη·
  2. καλέστε το UseDoconutResources() πριν από το UseDoconut()·
  3. διατηρήστε το ResourcesPath, τα παραγόμενα URLs πόρων, και το ResPath του πελάτη ευθυγραμμισμένα·
  4. διατηρήστε το κλαδί που χαρτογραφείτε και το BasePath του πελάτη ευθυγραμμισμένα.

MiddlewarePath είναι επικυρωμένη ρύθμιση· δεν δημιουργεί κλαδί ASP.NET Core από μόνο του.

5. Κατασκευή και διάρκεια ζωής του Viewer

Αφαιρέστε τις κρυφές μνήμες που ανήκουν στην εφαρμογή για αντικείμενα Viewer. Δεν απομένει τίποτα σε ένα Viewer που αξίζει να διατηρηθεί: δεν μεταφέρει κατάσταση εγγράφου, και η κρυφή μνήμη συνεδρίας κατέχει τα πάντα που υπερβαίνουν τη διάρκεια ενός αιτήματος. Ενσωματώστε το σε ένα endpoint, Razor page, controller ή scoped υπηρεσία εφαρμογής:

csharp
app.MapPost("/api/open", async (Viewer viewer) =>
{
    var token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
    return Results.Ok(new { token });
});

Το επιστρεφόμενο token αναγνωρίζει μια συνεδρία εγγράφου στο διακομιστή. Θεωρήστε το ως διακριτικό πρόσβασης: μην το καταγράψετε, μην το αποθηκεύσετε μόνιμα και μην το χρησιμοποιήσετε σε αναλύσεις.

6. Άνοιγμα και κλείσιμο εγγράφων

Αντικαταστήστε το συγχρονικό OpenDocument(...) με το OpenDocumentAsync(...):

csharp
// Τρέχουσα ενσωμάτωση: Ο Viewer λαμβάνεται από το DI και το άνοιγμα εγγράφου είναι ασύγχρονο.
var token = await viewer.OpenDocumentAsync(path, new PdfConfig { AllowSearch = true });

Οι τρέχουσες υπερφορτώσεις δέχονται διαδρομή αρχείου ή ροή, προαιρετική διαμόρφωση μορφής, προαιρετικό DocOptions και ένα token ακύρωσης. Κλείστε ρητά τη συνεδρία του διακομιστή όταν ο περιηγητής δεν τη χρειάζεται πλέον:

csharp
viewer.CloseDocument(token);

Διαγράψτε οποιαδήποτε κλήση InitCache() και τη σημαία που την προστατεύει — δεν υπάρχει τίποτα που να χρειάζεται προθέρμανση με το χέρι. Μην επαναχρησιμοποιήσετε ένα token που δημιουργήθηκε από την προηγούμενη βιβλιοθήκη μετά τη μετάβαση: ανοίξτε ξανά κάθε έγγραφο μέσω του τρέχοντος API.

7. Web farm → κατανεμημένο: η μεγαλύτερη αλλαγή

UseDoconutWebFarm και WebFarmOptions δεν υπάρχουν πλέον. Αν η εφαρμογή σας τα καλεί, αυτή η ενότητα είναι η αναβάθμισή σας· αν όχι, παραλείψτε στο §8.

Προηγουμένως ένα middleware έκανε τα πάντα: παρείχε προ‑αποδομένες εικόνες από έναν κοινόχρηστο φάκελο, και έλεγχε ενώ ένας άλλος κόμβος συνέχιζε να τις γράφει.

csharp
// Προηγούμενη ενσωμάτωση — μία κλήση, έμμεση συντονισμός μέσω του συστήματος αρχείων.
appBranch.UseDoconutWebFarm(new WebFarmOptions
{
    Path                = Path.Combine(env.WebRootPath, "webfarm"),
    PageWaitTimeSeconds = 180,
    StartWaitFromPage   = 5,
});

Η ίδια εργασία τώρα χωρίζεται σε δύο ρητές μισές. Μέρος εγγραφής — ο κόμβος που ανοίγει το έγγραφο δημοσιεύει ολόκληρο το σύνολο των τεχνητών (σελίδες, πληροφορίες εγγράφου, ευρετήριο αναζήτησης, μεταδεδομένα) στο κοινόχρηστο χώρο:

csharp
var result = await _publisher.PublishAsync(          // DistributedDocumentPublisher, ενσωματωμένο από το DI
    pathToFile,
    new FileShareConfig
    {
        Location              = CloudLocation.FileShare,
        RootPath              = @"\\fileserver\doconut",   // ο ίδιος φάκελος που χρησιμοποιείτε σήμερα
        UsePerTokenSubfolders = true,
    },
    config,
    documentOptions,
    new DistributedDocumentPublishOptions
    {
        CleanUpStagingDirectory = true,
        FirstPagePriority       = true,
    });

return Content(result.Token);

Μέρος ανάγνωσης — οποιοσδήποτε κόμβος εξυπηρετεί από το κοινόχρηστο χώρο:

csharp
app.MapWhen(
    ctx => ctx.Request.Path.Value?.EndsWith("DocImage.axd", StringComparison.OrdinalIgnoreCase) == true,
    branch => branch.UseDoconutCloud<FileShareCloudHandler>(options =>
    {
        options.Location          = CloudLocation.FileShare;
        options.CloudUploadConfig = /* η ΙΔΙΑ FileShareConfig όπως παραπάνω */;
    }, "/"));
ΠρινΤώρα
WebFarmOptions.PathFileShareConfig.RootPath
PageWaitTimeSeconds / StartWaitFromPageαπών — αντικαταστάθηκε από FirstPagePriority στο μέρος εγγραφής συν FileShareConfig.ReadReadyPollMs στο μέρος ανάγνωσης
viewer.OpenDocument(...) then viewer.ExportToPng(share)μία κλήση PublishAsync(...)
DocOptions.IsWebfarm / WebfarmPathακόμα υπάρχει, ονομάζεται IsWebFarm / WebFarmPath — αλλά δεν χρειάζεται στη διαδρομή δημοσίευσης

Η τοπολογία σας δεν αλλάζει. Κατευθύνετε το RootPath στον ίδιο UNC κοινόχρηστο φάκελο και κάθε κόμβος συνεχίζει να λειτουργεί όπως σήμερα. Η αλλαγή είναι ότι η δημοσίευση είναι μια ενέργεια που καλείτε, αντί για παρεμπόδιση της απόδοσης.

Και τα δύο μισά πρέπει να συμφωνούν. Αν το RootPath ή το UsePerTokenSubfolders διαφέρουν μεταξύ του εκδότη και του χειριστή, ο άλλος κόμβος επιστρέφει 404. Δημιουργήστε τη διαμόρφωση σε ένα βοηθητικό εργαλείο και καλέστε την και από τις δύο πλευρές.

PageWaitTimeSeconds = 180 σήμαινε «αποκλεισμός έως τρία λεπτά ελπίζοντας να εμφανιστεί η σελίδα». Η αντικατάσταση είναι ρητή: με FirstPagePriority = true, η σελίδα 1 είναι άμεσα εξυπηρετήσιμη και οι επόμενες σελίδες απαντούν HTTP 202 Accepted μέχρι να γραφτούν. Ο ενσωματωμένος viewer επαναπροσπαθεί αυτόματα όταν είναι ορισμένο το retryOn409. Ένας πελάτης που δεν επαναπροσπαθεί θα εμφανίσει σπασμένα πλακίδια για σελίδες που εξακολουθούν να αποδίδονται.

Η πλήρης διάταξη, συμπεριλαμβανομένης της παρασκηνιακής δημοσίευσης και των εισιτηρίων πρόσβασης, περιγράφεται στις Διανεμημένες Αναπτύξεις.

8. Η μετατροπή είναι ένα πρόσθετο, και πολύ μικρότερο

Καταχωρίστε το πρόσθετο, μετά ενσωματώστε το περιτύλιγμα DocumentConverter:

csharp
builder.Services.AddDoconut(o => o.AddPlugin<ConverterPlugin>());
csharp
// Προηγούμενη ενσωμάτωση
var converter = viewer.Converter.GetConverter();
var config    = new WordConfigConverter { TargetFormat = WordConfigConverter.EnTargetFormat.PDF };
var result    = converter.Convert(stream, SourceFormatConverter.DOCX, config);

// Τρέχουσα ενσωμάτωση
var result = await _converter.ConvertAsync(stream, ".docx", ConversionTarget.Pdf, null, ct);

Τι αντικαθιστά αυτό:

  • SourceFormatConverter — αφαιρέθηκε. Περάστε την επέκταση του αρχείου ως συμβολοσειρά, συμπεριλαμβανομένου του σημείου.
  • Οι τύποι *ConfigConverter ανά οικογένεια (WordConfigConverter, ExcelConfigConverter, …), καθένας με ενσωματωμένο enum EnTargetFormat — αφαιρέθηκαν. Τώρα υπάρχει ένα enum ConversionTarget για κάθε οικογένεια.
  • viewer.Converter.GetConverter() — αφαιρέθηκε. Ενσωματώστε το Doconut.DocumentConverter.

ConvertAsync επιστρέφει ένα ρεύμα που μπορεί να αναζητηθεί, έτσι το return File(result, mime, name) λειτουργεί άμεσα — η αντιγραφή MemoryStream που χρειαζόταν ο παλιός κώδικας είναι περιττή. Στο παραδιδόμενο παράδειγμα αυτό διέγραψε έναν διακόπτη επεκτάσεων με 68 περιπτώσεις και δέκα σχεδόν πανομοιότυπους ελεγκτές.

Δείτε το Πρόσθετο Μετατροπέα για την πλήρη λειτουργικότητα.

9. Πάροχοι cloud

UseDoconutCloud έγινε γενικό. Ο πάροχος είναι το τύπο‑όρισμα αντί για μια τιμή Location που ελέγχεται μέσα στο middleware:

csharp
// Προηγούμενη ενσωμάτωση
appBranch.UseDoconutCloud(new CloudOptions { Location = CloudLocation.CDN, ... });

// Τρέχουσα ενσωμάτωση
branch.UseDoconutCloud<CDNCloudHandler>(options =>
{
    options.Location          = CloudLocation.CDN;
    options.CloudUploadConfig = new CDNConfig { DoconutCdnUrl = "..." };
}, "/");

Οι κλάσεις διαμόρφωσης παραμένουν αμετάβλητες εκτός από το namespace (Doconut.Configs.Cloud → Doconut.Clouds): AzureConfig, AmazonConfig, GoogleCloudConfig, DropBoxConfig, RedisConfig, CDNConfig, FTPConfig, καθώς και το νέο FileShareConfig. Οι χειριστές ονομάζονται <Provider>CloudHandler.

Ο χειριστής CDN είναι μόνο για ανάγνωση — εξυπηρετεί ό,τι υπάρχει ήδη στο CDN· δεν κάνει ανεβάσματα.

10. Αντικείμενα ρυθμίσεων που άλλαξαν όνομα

ΠρινΤώρα
DoconutOptions.UnSafeModeUnsafeMode
DocOptions.IsWebfarmIsWebFarm
DocOptions.WebfarmPathWebFarmPath
DocOptions.ImageResolutionακόμα υπάρχει αλλά παρωχημένο — ορίστε την ανάλυση στη διαμόρφωση μορφής αντί αυτού

DocOptions προσθέτει επίσης το IsSecured.

Το τρέχον API διαχωρίζει επίσης τις ανησυχίες πιο αυστηρά από το προηγούμενο, έτσι ελέγξτε ότι κάθε ρύθμιση βρίσκεται στο αντικείμενο που τώρα την κατέχει:

ΑντικείμενοΤρέχων τύπος
Διαδρομές middleware, αδειοδότηση, καταχώρηση πρόσθετωνDoconutOptions
Κωδικός πρόσβασης, χρονικό όριο, ασφάλεια, υδατογράφημαDocOptions
Απόδοση μορφής και DPIPdfConfig, WordConfig, ExcelConfig και άλλοι τύποι BaseConfig
Προεπιλογές widget προγράμματος περιήγησηςViewerConfig ή οι αντίστοιχες επιλογές JavaScript
Παραγόμενα CSS και scriptsCssConfig και ScriptConfig
Κοινόχρηστη αποθήκευση και πάροχοι cloudFileShareConfig και οι άλλες ρυθμίσεις Doconut.Clouds

Μην μεταφέρετε το DocOptions.ImageResolution ως έλεγχο απόδοσης. Είναι παρωχημένο· ορίστε το BaseConfig.ImageResolution στη διαμόρφωση ειδική για τη μορφή. Εξετάστε όλα τα προεπιλεγμένα αντί να υποθέτετε ότι μια προηγούμενη διαμόρφωση έχει την ίδια συμπεριφορά.

11. Ο προβολέας στην πλευρά του πελάτη — δύο αλλαγές που αποτυγχάνουν σιωπηρά

Και τα δύο αυτά αφήνουν τον διακομιστή να λειτουργεί τέλεια. Το έγγραφό σας αποδίδεται, η σελίδα φαίνεται σωστή και δεν εμφανίζεται τίποτα στην κονσόλα του προγράμματος περιήγησης. Διαβάστε αυτήν την ενότητα ακόμη και αν ο κώδικας C# σας μεταγλωττίζεται στην πρώτη προσπάθεια.

Οι κλήσεις επιστροφής του προβολέα είναι τώρα επιλογές, όχι παγκόσμιες συναρτήσεις

Ο προηγούμενος προβολέας κάλεσε τους χειριστές σας με όνομα, αντλώντας το όνομα της παγκόσμιας συνάρτησης από το id του container. Η δήλωση function ctlDoc_OnViewerReady() σε μια σελίδα με <div id="div_ctlDoc"> ήταν αρκετή. Ο τρέχων προβολέας λαμβάνει ρητές κλήσεις επιστροφής στο αντικείμενο επιλογών και δεν ψάχνει πλέον για αυτές τις παγκόσμιες μεταβλητές:

javascript
objctlDoc = $("#div_ctlDoc").docViewer({
    // ... οι υπάρχουσες επιλογές σας ...
    onViewerBusy:     ctlDoc_OnViewerBusy,      // βρέθηκε με όνομα
    onViewerReady:    ctlDoc_OnViewerReady,     // βρέθηκε με όνομα
    onCopy:           ctlDoc_Copy,              // ήταν ctlDoc_Copy(text)
    onAutoLoadStatus: ctlDoc_AutoLoadStatus     // ήταν ctlDoc_AutoLoadStatus(page)
});

Γιατί αυτό είναι προβληματικό: η παλιά κλήση ήταν τυλιγμένη σε ένα κενό catch, το οποίο έπνιγε όλα. Τώρα οι συναρτήσεις σας απλώς δεν εκτελούνται ποτέ και δεν αναφέρεται κανένα σφάλμα. Το συνηθισμένο σύμπτωμα είναι ένας φορτωτής που παραμένει ενεργός — επειδή η συνάρτηση που το κρύβει ήταν η ctlDoc_OnViewerReady. Το έγγραφο πίσω από αυτό είναι εντάξει.

Η πλήρης λίστα επιλογών είναι onPageLoading, onPageLoaded, onThumbnailClicked, onPageClicked, onDoubleClick, onViewerBusy, onViewerReady, onViewerError, onCopy, onAnnSaved, onAnnSaveError, onAnnLoaded, onAnnClosed, onAutoLoadStatus, onThumbsShown και onError. Δεν υπάρχει κλήση επιστροφής για κλικ σε σύνδεσμο: η διαχείριση υπερσυνδέσμων είναι ενσωματωμένη, καθοδηγούμενη από το showHyperlinks.

ResPath πρέπει να δείχνει στο πρόθεμα πόρων

javascript
ResPath: '',                      // ΠΡΙΝ — οι πόροι προέρχονταν από τη ρίζα της εφαρμογής
ResPath: 'doconut-res/images',    // ΤΩΡΑ — το πρόθεμα που τοποθετεί η UseDoconutResources()

Αν αλλάξατε το πρόθεμα μέσω του DoconutOptions.ResourcesPath, χρησιμοποιήστε αυτήν την τιμή αντί αυτού.

12. Γραμμή εργαλείων Viewer, Αναζήτηση και Σχόλιο

Μην μεταφέρετε τα παλιά σενάρια ένα-ένα. Οι τρέχουσες εφαρμογές αναφοράς δημιουργούν ένα πλήρες πακέτο σελίδας:

  1. εκδώστε το CSS του Viewer και το αδειοδοτημένο CSS Αναζήτησης/Σχόλιου με το ReferenceCss·
  2. αποδώστε τη γραμμή εργαλείων Viewer που ανήκει στην εφαρμογή·
  3. αποδώστε το searchBarMount, annBarMount και το απαιτούμενο mount του Viewer·
  4. εκδώστε τα σενάρια του Viewer και των αδειοδοτημένων μονάδων με το ReferenceScripts·
  5. φορτώστε το δικό της βοηθητικό σενάριο γραμμής εργαλείων της εφαρμογής·
  6. αρχικοποιήστε ένα objViewer·
  7. αρχικοποιήστε τις αδειοδοτημένες ταινίες Αναζήτησης και Σχόλιου·
  8. καλέστε το attach(objViewer) σε κάθε ταινία·
  9. ανοίξτε το έγγραφο και καλέστε το objViewer.View(token).

Η Αναζήτηση και το Σχόλιο είναι μονάδες που συνδέονται στον ίδιο Viewer, όχι ανεξάρτητες γραμμές εργαλείων. Η κύρια γραμμή εργαλείων ανήκει στην εφαρμογή-ξενιστή· οι ταινίες Αναζήτησης και Σχόλιου είναι ενσωματωμένες, πόροι με περιορισμό δυνατοτήτων.

Αφαιρέστε τα χειροκίνητα αντιγραμμένα αρχεία όπως documentLinks.js και docViewer.UI.js μόνο αφού η τρέχουσα σελίδα λειτουργεί με τους πόρους που εκδίδονται από το ReferenceCss και το ReferenceScripts.

13. Καταχώριση προσθέτων

Οι στατικές μέθοδοι αδειοδότησης προσθέτων δεν καταχωρούν τα τρέχοντα πρόσθετα. Εγκαταστήστε και καταχωρίστε ρητά κάθε εκδοθέν πακέτο:

csharp
builder.Services.AddDoconut(options =>
{
    options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
    options.AddPlugin<Doconut.Plugins.Dicom.DicomPlugin>();
});

AddDoconut() επικυρώνει τις καταχωρημένες δυνατότητες προσθέτων κατά την εκκίνηση. Τα Converter και DICOM είναι τα εκδοθέντα πρόσθετα .NET Standard. Η κανονική Αναζήτηση και το Σχόλιο είναι ενσωματωμένες αδειοδοτημένες λειτουργίες, όχι πακέτα AddPlugin<TPlugin>().

14. Συνεδρία και ασφάλεια εγγράφου

Η τρέχουσα ενσωμάτωση συνδέει έγγραφα με αδιαφανή διακριτικά και προσωρινές συνεδρίες. Με την προεπιλογή UnsafeMode = false, το UseDoconut() προσθέτει ασφάλεια πρόσβασης εγγράφων και ο ξενιστής πρέπει να ρυθμίσει τη συνεδρία ASP.NET:

csharp
builder.Services.AddDistributedMemoryCache(); // η κατάσταση συνεδρίας χρειάζεται μια κρυφή μνήμη (MVC/Razor Pages την προσθέτουν ήδη)
builder.Services.AddSession();
app.UseSession();

Διατηρήστε το DocOptions.IsSecured = true εκτός εάν ένα ελεγμένο σχέδιο απαιτεί το αντίθετο. Ποτέ μην χρησιμοποιείτε το UnsafeMode = true ως συντόμευση μετάβασης σε έναν μοναδικό κόμβο. Δοκιμάστε αιτήματα χωρίς διακριτικό, με κατεστραμμένο διακριτικό, με ληγμένο διακριτικό και με διακριτικό από διαφορετική συνεδρία προγράμματος περιήγησης.

Σε ένα περιβάλλον farm, το αίτημα σελίδας μπορεί να φτάσει σε έναν κόμβο που δεν είδε ποτέ το αρχικό αίτημα, οπότε ο έλεγχος ανά συνεδρία θα το απορρίψει. Αυτή είναι η μόνη περίπτωση όπου το UnsafeMode = true είναι σωστό — και πρέπει να συνδυάζεται με υπογεγραμμένα εισιτήρια πρόσβασης μέσω του AddDoconutDistributedDocumentSecurity, όχι αυτόνομα. Δείτε το Διανεμημένες Αναπτύξεις.

Σημείωση ονοματολογίας

Σε όλα τα πλαίσια, η κλάση είναι Viewer. Αν βρείτε το DocumentViewer σε παλιές αποσπάσματα ή άρθρα τρίτων, αυτός ο τύπος δεν υπήρχε ποτέ στο SDK.

15. Προτεινόμενη σειρά εργασιών

  1. Επιβεβαιώστε ότι το πλαίσιο-ξενιστής μπορεί να καταναλώσει το netstandard2.1. Αν δεν μπορεί, σταματήστε.
  2. Αναβαθμίστε το πακέτο στην 26.8.0 και κάντε build. Επεξεργαστείτε τα σφάλματα μεταγλώττισης — τα περισσότερα είναι οι γραμμές using στο §1.
  3. Μετακινήστε την εκκίνηση στο AddDoconut() και τις κλήσεις middleware στη νέα τους σειρά (§3, §4).
  4. Ενσωματώστε το Viewer εκεί που το κατασκευάζατε, κάντε το OpenDocument ασύγχρονο και διαγράψτε το InitCache() (§5, §6).
  5. Αν χρησιμοποιείτε το web farm, κάντε το §7 — το μοναδικό μέρος που είναι επανασχεδίαση αντί για μετονομασία.
  6. Αν μετατρέπετε έγγραφα, κάντε το §8.
  7. Κάντε το §11 — τις αλλαγές στην πλευρά του πελάτη. Αυτές είναι οι αλλαγές που δεν θα ανακοινωθούν αυτόματα.
  8. Ανοίξτε ένα πραγματικό έγγραφο σε πρόγραμμα περιήγησης και παρακολουθήστε το περιστρεφόμενο εικονίδιο φόρτωσης. Μια πράσινη κατασκευή δεν αποδεικνύει τίποτα εδώ: η αδειοδότηση, η καταχώριση προσθέτων, το μονοπάτι πόρων και οι κλήσεις επιστροφής του viewer αποτυγχάνουν μόνο σε χρόνο εκτέλεσης. Για ένα farm, επαληθεύστε ότι ένα έγγραφο που δημοσιεύθηκε από έναν κόμβο εξυπηρετείται από έναν άλλο.

Δοκιμή της μετανάστευσης

Σε ελάχιστο επίπεδο, επαληθεύστε:

  • εκκίνηση της εφαρμογής με την παραγωγική άδεια και κάθε καταχωρημένο πρόσθετο·
  • CSS/σενάρια του Viewer και όλα τα αιτήματα σελίδας-εικόνας κάτω από τις επιλεγμένες διαδρομές·
  • άνοιγμα εγγράφου, πλοήγηση, ζουμ, μικρογραφίες, εκτύπωση και ρητό κλείσιμο·
  • Αναζήτηση σε έγγραφο με κείμενο και η μη-αναζητήσιμη κατάσταση αρχείου μόνο με εικόνα·
  • φόρτωση, αποθήκευση, εξαγωγή σχολίων και έλεγχος δυνατοτήτων·
  • ανακάλυψη στόχου μετατροπέα, έξοδος, λήψη και κατάσταση υδατογραφήματος·
  • σελίδες DICOM, καρέ και animation· η τεχνική μετα-δεδομένα δεν είναι διαθέσιμα σε αυτό το πακέτο·
  • έγγραφα με προστασία κωδικού, προσαρμοσμένες γραμματοσειρές, μη-λατινικό κείμενο και ρυθμισμένα χρονικά όρια·
  • απόρριψη διακριτικού μεταξύ συνεδριών και συμπεριφορά ληγμένης συνεδρίας·
  • για ένα farm: δημοσίευση σε έναν κόμβο, αίτηση μιας καθυστερημένης σελίδας από άλλον και επιβεβαίωση ότι ο viewer επαναπροσπαθεί απαντήσεις 202 αντί να εμφανίζει σπασμένα πλακίδια·
  • κινητές συσκευές, σκοτεινή λειτουργία και η διαδρομή reverse-proxy παραγωγής.

Σχέδιο επαναφοράς

Διατηρήστε το προηγούμενο αντικείμενο ανάπτυξης, τα αντίστοιχα πακέτα, τα αρχεία άδειας και τους αντιγραμμένους πόρους του προγράμματος περιήγησης μαζί. Μια ασφαλής επαναφορά αλλάζει ολόκληρη τη γενιά της εφαρμογής· δεν αναμιγνύει διακομιστή προηγούμενης γενιάς με τρέχοντα σενάρια, ή τρέχοντα διακομιστή με σημεία κλήσης new Viewer(...).

Πριν από τη μετάβαση, καταγράψτε:

  • το slot ή το αντικείμενο ανάπτυξης που χρησιμοποιείται για επαναφορά·
  • την επίδραση του κοινόχρηστου αποθηκευτικού χώρου, εάν υπάρχει — τα αντικείμενα που δημοσιεύτηκαν από την έκδοση 26.8.0 δεν καταναλώνονται από το προηγούμενο middleware του web-farm·
  • πώς θα ακυρωθούν οι ενεργές συνεδρίες εγγράφων·
  • τον έλεγχο υγείας και το δοκιμαστικό έγγραφο που χρησιμοποιείται για την απόφαση επαναφοράς·
  • ποιος μπορεί να επαναφέρει το προηγούμενο σύνολο πακέτων και τη διαμόρφωση.

Παλαιά τεκμηρίωση

Το μεταφρασμένο προηγούμενο εγχειρίδιο παραμένει διαθέσιμο στο Legacy .NET Standard setup. Το Previous integration gateway εξηγεί τα ίδια σήματα ταυτοποίησης και συνδέεται πίσω σε αυτόν τον οδηγό μετανάστευσης.

Διατηρήστε το ιστορικό URL σε σελιδοδείκτες και εισιτήρια υποστήριξης όσο υπάρχουν εγκαταστάσεις netstandard2.0. Καταγράφει μια διαφορετική γενιά και δεν ανακατευθύνει στο τρέχον API.

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