Tutorial: Abrir documentos con el visor Doconut inyectado en .NET 8
← Back to Blog••5 min read

Tutorial: Abrir documentos con el visor Doconut inyectado en .NET 8

Introducción

Los ejemplos más antiguos de Doconut pueden construir Viewer directamente con argumentos de caché, contexto HTTP y ruta de licencia. Eso no es el modelo de integración actual de .NET 8. AddDoconut() registra Viewer con inyección de dependencias, y los puntos finales de la aplicación reciben el servicio en lugar de llamar a un constructor.

Componentes de servidor abstractos pasando un token de sesión opaco a una superficie de visualización de documentos
Componentes de servidor abstractos pasando un token de sesión opaco a una superficie de visualización de documentos

Este tutorial sigue el flujo de solicitud actual: registrar servicios y middleware, emitir los recursos incrustados del visor, abrir un documento con OpenDocumentAsync, devolver un token de sesión opaco y pasar ese token al widget del navegador.


1. Instalar y registrar Doconut

Agregar el paquete .NET 8:

dotnet add package Doconut.NET8

Registrar Doconut y los servicios de sesión de ASP.NET:

builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
    options.MiddlewarePath = "/doconut";
    options.ResourcesPath = "/doconut-res";
    options.UnsafeMode = false;
});

builder.Services.AddSession();

Conectar el middleware en el orden requerido. El middleware de recursos debe ejecutarse antes del middleware terminal de documentos:

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

MiddlewarePath coordina la configuración pero no crea la rama de ASP.NET por sí mismo. La ruta mapeada /doconut debe coincidir con el BasePath del widget.

2. Añadir la superficie del visor y los recursos

El visor de navegador Doconut es un plugin de jQuery. En una página Razor, inyecte Viewer y solicite que emita las etiquetas de recursos en orden de dependencia:

@inject Doconut.Viewer Viewer

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

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

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

Inicialice el widget con rutas que coincidan con el registro del servidor:

const objViewer = $('#div_ctlDoc').docViewer({
    showThumbs: true,
    autoLoad: false,
    pageZoom: 100,
    FitType: 'width',
    BasePath: '/doconut',
    ResPath: '/doconut-res/images',
    onError: function (message) {
        console.error('Doconut viewer error:', message);
    }
});

La capitalización de las opciones es significativa. Use los nombres mostrados por la versión instalada en lugar de normalizarlos a un único estilo.

3. Inyectar Viewer y abrir un documento

Viewer está registrado como un servicio transitorio. Resuélvalo mediante inyección en el punto final, inyección de constructor o la facilidad equivalente en su aplicación ASP.NET Core.

app.MapPost("/api/open", async (
    Viewer viewer,
    CancellationToken ct) =>
{
    string token = await viewer.OpenDocumentAsync(
        "wwwroot/files/Sample.pdf",
        ct: ct);

    return Results.Ok(new { token });
});

Para una carga, proporcione un flujo y un FileInfo cuya extensión identifique el formato de origen:

app.MapPost("/api/open-upload", async (
    IFormFile file,
    Viewer viewer,
    CancellationToken ct) =>
{
    await using var stream = file.OpenReadStream();
    string token = await viewer.OpenDocumentAsync(
        stream,
        new FileInfo(file.FileName),
        ct: ct);

    return Results.Ok(new { token });
});

Valide el tamaño de la carga, la extensión y la autorización antes de abrir contenido suministrado por el usuario. No convierta el nombre de archivo enviado en una ruta del servidor.

4. Pasar el token al widget

Obtenga el punto final de apertura y entregue el token devuelto a objViewer.View:

fetch('/api/open', { method: 'POST' })
    .then(response => {
        if (!response.ok) throw new Error('The document could not be opened.');
        return response.json();
    })
    .then(data => objViewer.View(data.token))
    .catch(error => console.error(error));

Trate el token como una credencial portadora para una sesión de documento en vivo:

  • No lo registre ni lo persista.
  • Devuélvalo solo a un cliente autorizado.
  • No exponga la ruta del archivo fuente.
  • Reabra el documento cuando una sesión expire.
  • Cierre la sesión cuando el documento ya no sea necesario.

5. Cerrar sesiones del lado del servidor deliberadamente

El código del cliente puede llamar a objViewer.Close() cuando el usuario abandona el visor. Los flujos de trabajo del servidor también pueden revocar un token conocido explícitamente:

app.MapPost("/api/close", (string token, Viewer viewer) =>
{
    viewer.CloseDocument(token);
    return Results.NoContent();
});

El cierre explícito es especialmente útil para documentos grandes. La expiración de la sesión sigue siendo una solución de respaldo, no un sustituto de una gestión predecible del ciclo de vida de la aplicación.

6. Añadir módulos opcionales solo después de que el núcleo funcione

La búsqueda y las anotaciones se adjuntan al mismo visor inicializado. Añada sus CSS, scripts, montajes, verificaciones de licencia y devoluciones de llamada del ciclo de vida solo después de que el flujo base tenga éxito:

AddDoconut + session services
    -> UseSession
    -> UseDoconutResources
    -> mapped UseDoconut branch
    -> viewer resources and mount
    -> initialize docViewer
    -> OpenDocumentAsync
    -> objViewer.View(token)

Este orden mantiene los fallos de renderizado del núcleo separados de la configuración de módulos opcionales.

Errores comunes de migración

Patrón antiguo o incorrectoDirección actual de .NET 8
new Viewer(cache, accessor, licensePath)Inyecte Viewer después de AddDoconut()
Llamadas estáticas de carga de licencia en el código de solicitudConfigure la entrada de licencia en AddDoconut()
Ejemplos síncronos de OpenDocument(...)Use OpenDocumentAsync(...)
Un CDN externo o inventado del visorEmita recursos incrustados con ReferenceCss y ReferenceScripts
Una API genérica de JavaScript init()Inicialice $('#div_ctlDoc').docViewer(...)
Persistir el token del visorPersista su ID de documento; trate el token como temporal

Use la documentación oficial de documentación de Doconut y verifique los ejemplos con la versión del paquete instalado antes de adaptarlos al código de producción.

#Doconut#.NET 8#Visor de Documentos#ASP.NET Core#JavaScript