Avvio Rapido

Visualizza il tuo primo documento in pochi minuti

Questo tutorial porta un'app ASP.NET Core da un Program.cs vuoto a un documento visualizzato nel browser: registrazione del server, il pacchetto completo del Viewer (barra degli strumenti del Viewer, montaggio del Viewer e nastri opzionali di Search/Annotation), riferimenti alle risorse, inizializzazione del client, apertura del documento ed esecuzione.

Configurazione del server

AddDoconut() registra i servizi; UseDoconutResources() e UseDoconut() collegano il middleware. La chiamata alle risorse deve avvenire per prima. Le chiamate alla sessione sono anch'esse necessarie — la sicurezza predefinita dei documenti Doconut convalida ogni richiesta di pagina contro lo stato della sessione ASP.NET. Hai già registrato Doconut durante l'Installazione? Salta alla sezione successiva.

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
});
builder.Services.AddSession(); // Doconut document security rides on ASP.NET session state

app.UseSession();          // call UseSession() before UseDoconut()
app.UseDoconutResources(); // must be registered before UseDoconut()
app.UseDoconut();

Per una struttura dei percorsi in stile produzione, mappa il middleware dei documenti a un ramo esplicito e mantieni allineate le quattro impostazioni dei percorsi:

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = Path.Combine(AppContext.BaseDirectory, "Doconut.Viewer.lic");
    options.MiddlewarePath = "/doconut";
    options.ResourcesPath = "/doconut-res";
    options.UnsafeMode = false;
});
builder.Services.AddSession();

app.UseRouting();
app.UseSession();
app.UseDoconutResources();
app.Map("/doconut", branch => branch.UseDoconut());

MiddlewarePath è un valore di coordinamento; non mappa un ramo ASP.NET Core da solo. In questo esempio l'host mappa /doconut, quindi il client deve usare BasePath: '/doconut'. ResourcesPath serve il bundle incorporato in /doconut-res, e il percorso delle risorse immagine del widget è quindi ResPath: '/doconut-res/images'.

Aggiungi il visualizzatore a una pagina

Il Viewer è il nucleo richiesto della pagina. La sua superficie di rendering utilizza due div annidati:

html
<div id="divDocViewer">
    <div id="div_ctlDoc"></div>
</div>

Tratta la barra degli strumenti, i mount dei moduli e la superficie del Viewer come un'unica composizione di pagina. Search e Annotation inseriscono i loro nastri incorporati nei mount opzionali, ma questi moduli non sono mai autonomi: si collegano sempre al Viewer nella stessa pagina. Usa lo stesso ordine di Doconut.TestApp e Doconut.TestApp.Distributed:

html
<nav id="toolbar" aria-label="Document viewer controls">
    <!-- Viewer navigation, zoom, Search, and Annotation buttons -->
</nav>

<div id="searchBarMount"></div>
<div id="annBarMount"></div>

<div id="divDocViewer">
    <div id="div_ctlDoc"></div>
</div>

Riferisci le risorse del visualizzatore

In una vista Razor, il servizio Viewer iniettato emette i tag <link> e <script> del visualizzatore in ordine di dipendenza — il widget è un plugin jQuery, quindi jQuery deve essere caricato prima degli script del visualizzatore:

html
@inject Doconut.Viewer Viewer

@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
    IncludeBootstrapCss = true,
    IncludeViewerCss    = true
}))

@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
    IncludeJQuery        = true,
    IncludeBootstrap     = true,
    IncludeViewerScripts = true
}))

Per il pacchetto completo del Viewer, richiedi insieme le risorse del Viewer e dei moduli:

html
@Html.Raw(Viewer.ReferenceCss(new CssConfig
{
    IncludeBootstrapCss  = true,
    IncludeViewerCss     = true,
    IncludeSearchCss     = true,
    IncludeAnnotationCss = true
}))

@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig
{
    IncludeJQuery             = true,
    IncludeBootstrap         = true,
    IncludeViewerScripts     = true,
    IncludeSearchScripts     = true,
    IncludeSearchBar         = true,
    IncludeAnnotationScripts = true,
    IncludeAnnotationBar     = true
}))

IncludeViewerCss e IncludeViewerScripts sono le flag core obbligatorie. Non pubblicare mai un esempio di Nastro di Search o Annotation senza di esse, il mount del Viewer e un'istanza docViewer. ReferenceCss e ReferenceScripts omettono le risorse di un modulo opzionale quando la licenza corrente non concede tale capacità; il core del Viewer si avvia comunque.

Inizializza il visualizzatore

Il widget lato client è un plugin jQuery. Questo è un set minimo di opzioni di inizializzazione reali (non pseudocodice):

javascript
let searchBar = null;
let annBar = null;

const objViewer = $('#div_ctlDoc').docViewer({
    showThumbs: true,
    autoLoad:   false,
    pageZoom:   100,
    FitType:    'width',
    BasePath:   '/doconut',
    ResPath:    '/doconut-res/images',
    onViewerReady: function () {
        // pages are visible; safe to hide a loading spinner here
    },
    // Forward annotation lifecycle events to the embedded ribbon when it is present.
    onAnnLoaded:    () => annBar?.handleAnnLoaded(),
    onAnnSaved:     () => annBar?.handleAnnSaved(),
    onAnnSaveError: () => annBar?.handleAnnSaveError(),
    onAnnClosed:    () => annBar?.handleAnnClosed(),
    onError: function (message) {
        console.error('Doconut viewer error:', message);
    }
});

Il caso delle lettere delle opzioni è davvero misto — showThumbs, autoLoad e pageZoom sono camelCase, ma FitType, BasePath e ResPath sono PascalCase. Non esiste una regola coerente; se il caso è sbagliato l'opzione viene silenziosamente ignorata (il widget ricade sul valore predefinito invece di generare un errore).

Assemblare il pacchetto completo del visualizzatore

Entrambe le applicazioni di riferimento .NET 8 installano le seguenti parti insieme in una pagina:

Parte del pacchettoRequisitoCome è collegata
Risorse del Viewer, mount e objViewerObbligatorioRenderer di documento core
Barra degli strumenti del ViewerObbligatorio nella composizione di riferimentoMarkup host; i pulsanti chiamano lo stesso objViewer
Nastro di ricercaModulo opzionale, con licenzadoconutSearchBar(...).attach(objViewer)
Nastro di annotazioneModulo opzionale, con licenzadoconutAnnotationBar(...).attach(objViewer)

Sebbene la barra degli strumenti principale del Viewer sia markup host, è installata insieme al Viewer e non deve mai essere documentata come un controllo isolato. Questo mantiene il suo layout, le etichette, le icone e le regole di autorizzazione sotto il controllo della tua applicazione, mentre ogni pulsante guida la stessa istanza del Viewer:

html
<nav id="toolbar" aria-label="Document viewer controls">
    <button type="button" onclick="objViewer.GotoPage(1)">First</button>
    <button type="button" onclick="objViewer.Next(false)">Previous</button>
    <button type="button" onclick="objViewer.Next(true)">Next</button>
    <button type="button" onclick="objViewer.GotoPage(objViewer.TotalPages())">Last</button>
    <button type="button" onclick="objViewer.Zoom(false)">Zoom out</button>
    <button type="button" onclick="objViewer.Zoom(true)">Zoom in</button>
    <button type="button" onclick="objViewer.FitType('width')">Fit width</button>
    <button type="button" onclick="objViewer.FitType('height')">Fit height</button>
    <button type="button" id="openSearch">Search</button>
    <button type="button" id="openAnnotations">Annotations</button>
</nav>

La barra degli strumenti di riferimento completa copia anche wwwroot/js/viewerToolbar.js nell'applicazione host per rotazione, miniatura, stampa, schermo intero, layout e helper per lo stato dei pulsanti. Carica quel file host dopo Viewer.ReferenceScripts(...). Mantieni l'helper e il suo markup <nav id="toolbar"> insieme quando copi l'implementazione demo completa.

Mantieni l'ordine di inizializzazione del pacchetto usato da entrambe le applicazioni di riferimento:

  1. Emettere le risorse del Viewer, Search e Annotation insieme.
  2. Renderizzare la barra degli strumenti del Viewer, i mount dei Nastri e il mount del Viewer insieme.
  3. Inizializzare docViewer per primo.
  4. Creare ogni Nastro con licenza e collegarlo allo stesso objViewer.
  5. Aprire il documento e conservare il suo token per le richieste dei moduli.

Doconut.TestApp.Distributed mantiene questa esatta composizione UI e lo stesso helper della barra degli strumenti del Viewer. Il suo valore di richiesta access aggiuntivo e le impostazioni di retry di rendering asincrono appartengono al trasporto distribuito; non modificano il modo in cui il Viewer, la barra degli strumenti o i Nastri sono assemblati.

Le guardie lato server sono importanti: quando una capacità opzionale non è disponibile, il suo script non viene emesso, quindi la funzione plugin jQuery non esiste.

html
<script>
    let currentToken = '';

    const refitViewer = () =>
        requestAnimationFrame(() => objViewer.Refit());

    @if (Viewer.IsSearchEnabled)
    {
        <text>
    searchBar = $('#searchBarMount').doconutSearchBar({
        docId: 'ctlDoc',
        getRequestParams: () => ({ token: currentToken }),
        onLayout: refitViewer
    });
    searchBar.attach(objViewer);
        </text>
    }

    @if (Viewer.IsAnnotationEnabled)
    {
        <text>
    annBar = $('#annBarMount').doconutAnnotationBar({
        docId: 'ctlDoc',
        getRequestParams: () => ({ token: currentToken }),
        onLayout: refitViewer
    });
    annBar.attach(objViewer);
        </text>
    }

    document.getElementById('openSearch').addEventListener('click', () => {
        if (!searchBar) return;
        searchBar.isOpen() ? searchBar.close() : searchBar.open();
    });

    document.getElementById('openAnnotations').addEventListener('click', () => {
        if (!annBar) return;
        annBar.isOpen() ? annBar.close() : annBar.open();
    });
</script>

Entrambi i componenti incorporati generano il proprio DOM del Nastro. Search contiene i gruppi Find, Options e Results. Annotation contiene i suoi strumenti di authoring, controlli di stile, azioni di salvataggio e azioni opzionali di export/image. Le barre espongono open(), close(), reset(), e isOpen(); chiama sempre attach(objViewer) una volta dopo averle create.

L'esempio sopra omette callback host opzionali e endpoint di export/image dell'Annotation per mantenere l'avvio minimale. Vedi Ricerca e Annotazioni per la configurazione completa delle funzionalità, o Temi personalizzati per stilizzare o sostituire la barra degli strumenti del Viewer di proprietà dell'host.

Apri un documento

Il lato server è un endpoint: il servizio Viewer iniettato apre il documento e restituisce un token di sessione.

csharp
app.MapPost("/api/open", async (Viewer viewer) =>
{
    // The token is opaque — hand it to the widget, never log or persist it.
    string token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
    return Results.Ok(new { token });
});

Il client recupera quel token e lo passa al widget con objViewer.View(token):

javascript
fetch('/api/open', { method: 'POST' })
    .then(resp => resp.json())
    .then(data => {
        currentToken = data.token;
        objViewer.View(currentToken);
    });

Chiudi il documento

Chiama objViewer.Close() quando l'utente lascia il visualizzatore o apre un documento di sostituzione. Nei flussi di lavoro guidati dal server, viewer.CloseDocument(token) rimuove immediatamente la sessione cache, dispone il motore di rendering, elimina il suo marcatore di sicurezza e revoca il token. L'espirazione scorrevole alla fine esegue la stessa pulizia, ma la chiusura esplicita è consigliata per documenti di grandi dimensioni.

Il flusso di richiesta completato è:

text
AddDoconut + middleware
    -> render CSS/scripts and mount div
    -> initialize docViewer
    -> OpenDocumentAsync
    -> return opaque token
    -> objViewer.View(token)
    -> page/search/annotation requests
    -> Close / CloseDocument

Tratta il token come una credenziale di tipo bearer: non registrarlo mai, non conservarlo, passalo solo al widget. Identifica una sessione documento attiva sul server e smette di funzionare quando quella sessione scade — riapri il documento per ottenerne uno nuovo.

Esegui

Posiziona un PDF in wwwroot/files/Sample.pdf, esegui dotnet run e apri la pagina che ospita il widget. La prima pagina viene renderizzata nel visualizzatore, con un pannello di miniature a sinistra. Se non accade, consulta Risoluzione dei problemi.

Cosa ottieni senza licenza

Una licenza mancante non genera eccezioni. Il visualizzatore si rende normalmente, ma ogni pagina presenta una filigrana di valutazione. Consulta Configurazione della licenza per capire come Doconut trova una licenza e cosa cambia una volta che lo fa.

Questa pagina è stata utile?