Tutorial: Abrir documentos con el visor Doconut inyectado en .NET 8
← Back to Blog5 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. Ese no es el modelo de integración actual de .NET 8. AddDoconut() registra Viewer mediante inyección de dependencias, y los puntos finales de la aplicación reciben el servicio en lugar de llamar a un constructor.

Componentes abstractos del servidor que pasan un token de sesión opaco a una superficie de visualización de documentos
Componentes abstractos del servidor que pasan 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 del visor incrustados, 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

Agrega el paquete .NET 8:

dotnet add package Doconut.NET8

Registra 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();

Conecta 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 jQuery. En una página Razor, inyecta Viewer y pídele 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>

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

El uso de mayúsculas en las opciones es significativo. Utiliza los nombres mostrados por la versión instalada en lugar de normalizarlos a un único estilo.

3. Inyectar Viewer y abrir un documento

Viewer se registra como un servicio transitorio. Resuélvelo mediante inyección en el punto final, inyección de constructor o la facilidad equivalente en tu 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, proporciona 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 });
});

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

4. Pasar el token al widget

Obtén el punto final de apertura y entrega 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));

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

  • No lo registres ni lo persistas.
  • Devuélvelo solo a un cliente autorizado.
  • No expongas la ruta del archivo fuente.
  • Vuelve a abrir el documento cuando una sesión expire.
  • Cierra la sesión cuando el documento ya no sea necesario.

5. Cerrar sesiones del lado del servidor de forma deliberada

El código 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 un mecanismo 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ñade sus CSS, scripts, montajes, verificaciones de licencia y callbacks de 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)Inyectar Viewer después de AddDoconut()
Llamadas estáticas de carga de licencia en el código de solicitudConfigurar la entrada de licencia en AddDoconut()
Ejemplos síncronos de OpenDocument(...)Usar OpenDocumentAsync(...)
Un CDN externo o inventado para el visorEmitir recursos incrustados con ReferenceCss y ReferenceScripts
API genérica de JavaScript init()Inicializar $('#div_ctlDoc').docViewer(...)
Persistir el token del visorPersistir tu ID de documento; tratar el token como temporal

Utiliza la documentación oficial de documentación de Doconut y verifica los ejemplos contra la versión del paquete instalado antes de adaptarlos a código de producción.

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