Inicio rápido
Renderiza tu primer documento en MVC 5 o Web Forms
Esta guía lleva una aplicación ASP.NET en .NET Framework 4.7.2 desde un paquete instalado hasta un documento renderizado en el navegador: Global.asax, un punto final de apertura, los recursos del visor, el widget y el token que los conecta. Asume que los registros en Web.config de Instalación están presentes — sin el controlador DocImage.axd y el módulo de recursos, nada de lo siguiente puede llegar al servidor.
Componer Doconut en Global.asax
Un Application_Start completo para una aplicación MVC 5:
// Global.asax.cs - compose once per worker process, release on shutdown.
protected void Application_Start()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Doconut.DoconutHost.Initialize(options =>
{
options.LicensePath = HostingEnvironment.MapPath("~/wwwroot/Doconut.Viewer.lic");
options.UnsafeMode = false; // a page is served only to the session that opened the document
});
// MVC only: keep the two Doconut endpoints out of routing.
RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
RouteTable.Routes.IgnoreRoute("doconut-res/{*pathInfo}");
}
protected void Application_End()
{
Doconut.DoconutHost.Shutdown();
}Encoding.RegisterProviderhace que las páginas de código heredadas que algunos formatos de documento utilizan estén disponibles para el proceso. Llámalo una sola vez, antes de que se abra el primer documento.UnsafeMode = falsees el valor predeterminado, escrito explícitamente para que nadie lo cambie por accidente:DocImage.axdsirve una página solo a la sesión ASP.NET que abrió el documento.- Las dos llamadas
IgnoreRoutemantienen el enrutamiento MVC alejado deDocImage.axdy/doconut-res/*, que son servidos por el controlador y el módulo. Una aplicación Web Forms no tiene rutas MVC y no necesita ninguna de estas líneas. DoconutHost.Shutdowndetiene el trabajo en segundo plano de Doconut y libera sus servicios cuando el pool de aplicaciones se recicla. Es seguro llamarlo incluso siInitializenunca se ejecutó.
Abrir un documento
Abrir un documento devuelve un token opaco. El widget envía ese token con cada solicitud de página.
En MVC 5, una acción de controlador resuelve el servicio Viewer desde DoconutHost.Services — MVC 5 no tiene inyección de constructor para él:
// POST /Document/Open
[HttpPost]
public async Task<ActionResult> Open()
{
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
// The token is opaque - hand it to the viewer, never log or persist it.
string token = await viewer.OpenDocumentAsync(Server.MapPath("~/files/Sample.pdf"));
return Json(new { token });
}El documento debe abrirse dentro de una solicitud que tenga estado de sesión, porque al abrirlo se concede a la sesión ASP.NET actual acceso a sus páginas. Los controladores MVC y las páginas Web Forms tienen estado de sesión por defecto. Un IHttpHandler personalizado no lo tiene, a menos que implemente System.Web.SessionState.IRequiresSessionState. Abre un documento desde un controlador sin ello, y el visor mostrará "No está autorizado para ver esta página." en cada página.
En Web Forms, la propia página puede abrir el documento en su code-behind. OpenDocument es la forma sincrónica de OpenDocumentAsync, destinada al code-behind que no utiliza páginas asíncronas:
// Default.aspx.cs
protected string Token;
protected void Page_Load(object sender, EventArgs e)
{
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
Token = viewer.OpenDocument(Server.MapPath("~/files/Sample.pdf"));
}Trata el token como una credencial portadora: nunca lo registres ni lo persistas; pásalo solo al widget. Deja de funcionar cuando la sesión del documento expira — abre el documento nuevamente para obtener uno nuevo.
Referenciar los recursos del visor
Viewer.ReferenceCss y Viewer.ReferenceScripts emiten las etiquetas <link> y <script> para los recursos incrustados, en orden de dependencia, apuntando a /doconut-res/. El widget es un plugin de jQuery, por lo que jQuery viene primero.
MVC 5. Las vistas no tienen @inject, así que genera las etiquetas en el controlador y pásalas a través de ViewBag:
public ActionResult Index()
{
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
ViewBag.ViewerCss = viewer.ReferenceCss(new CssConfig
{
IncludeBootstrapCss = true,
IncludeViewerCss = true
});
ViewBag.ViewerScripts = viewer.ReferenceScripts(new ScriptConfig
{
IncludeJQuery = true,
IncludeBootstrap = true,
IncludeViewerScripts = true
});
return View();
}@Html.Raw(ViewBag.ViewerCss)
...
@Html.Raw(ViewBag.ViewerScripts)Mantén ese trabajo en el controlador. MVC 5 compila las vistas cuando se sirven por primera vez, y sin un paquete de compilador adicional ese compilador solo entiende C# 5 — sin ?., sin $"...", sin nameof. Una vista que los usa se compila correctamente en Visual Studio, pero responde con un 500 vacío en el navegador.
Web Forms. Expón las mismas cadenas desde el code-behind y escríbelas con <%= %>:
<head>
<%= ViewerCss %>
</head>
<body>
...
<%= ViewerScripts %>
</body>IncludeViewerCss y IncludeViewerScripts son el núcleo obligatorio. Para añadir las cintas de Búsqueda y Anotación, también establece IncludeSearchCss, IncludeAnnotationCss, IncludeSearchScripts, IncludeSearchBar, IncludeAnnotationScripts y IncludeAnnotationBar. Ambos métodos omiten los archivos de una cinta cuando la licencia no concede esa capacidad; el visor sigue iniciándose.
Añadir el visor a una página
La superficie de renderizado son dos divs anidados:
<div id="divDocViewer">
<div id="div_ctlDoc"></div>
</div>Da al div externo una altura real — el visor llena su contenedor y lo mide al iniciarse. El visor no dibuja su propia barra de herramientas: GotoPage, Next, Zoom, FitType y el resto son métodos que tu página conecta a sus propios botones, colocados al lado del visor:
<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.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>
</nav>Inicializar el visor y mostrar el documento
Después de los scripts del visor, crea el widget y luego pásale el token:
var objViewer = $('#div_ctlDoc').docViewer({
showThumbs: true,
autoLoad: false,
pageZoom: 100,
FitType: 'width',
BasePath: '/', // '/' means DocImage.axd at the site root
ResPath: 'doconut-res/images', // no leading '/'
onViewerReady: function () {
// pages are visible; hide a loading indicator here
},
onError: function (message) {
console.error('Doconut viewer error:', message);
}
});
fetch('/Document/Open', { method: 'POST' })
.then(function (resp) { return resp.json(); })
.then(function (data) { objViewer.View(data.token); });En Web Forms, donde la página abre el documento por sí misma, las tres últimas líneas se convierten en objViewer.View('<%= Token %>');.
Cuatro detalles aquí fallan sin un mensaje de error:
BasePath: '/'apunta aDocImage.axden la raíz del sitio. Para una aplicación en un directorio virtual, usa su nombre sin barras ('myapp'solicita/myapp/DocImage.axd). Una barra inicial ('/myapp') produce//myapp/DocImage.axd, que el navegador interpreta como una solicitud a otro host.ResPath: 'doconut-res/images'— los íconos están una carpeta bajo la raíz de recursos. Con'doconut-res', cada ícono devuelve 404: no hay glifos de la barra de herramientas ni spinner de carga, aunque el documento sigue renderizándose. Una barra inicial lo rompe de la misma manera queBasePath.- Los callbacks son opciones.
onViewerReady,onErrory los demás van en el objeto pasado adocViewer(...). Una función global nombrada como el visor, por ejemploctlDoc_ViewerReady, nunca se llama. - Mantén el visor, luego llama a
Viewpor separado.docViewer(...)devuelve el objeto conZoom,NextyFitType;View(...)devuelve otra cosa.var objViewer = $('#div_ctlDoc').docViewer({...}).View(token)renderiza el documento, pero falla conobjViewer.Zoom is not a functional hacer clic en la primera herramienta de la barra.
Los nombres de opciones mezclan camelCase (showThumbs, autoLoad, pageZoom) y PascalCase (FitType, BasePath, ResPath). Una opción mal escrita se ignora, y el widget usa su valor predeterminado.
La alternativa de una sola línea
Para una página que solo necesita mostrar un documento, sin una barra de herramientas propia, Viewer.RenderViewer escribe todo el script de inicialización — docViewer(...) con BasePath: '/' y ResPath: 'doconut-res/images', luego .View(token). Existe únicamente en este paquete:
// Web Forms code-behind, after opening the document
ViewerInit = viewer.RenderViewer("div_ctlDoc", Token);<div id="div_ctlDoc" style="height: 100vh"></div>
<%= ViewerScripts %>
<%= ViewerInit %>Pase un ViewerConfig como tercer argumento para cambiar el zoom, el ajuste o el panel de miniaturas. Debido a que el script generado no mantiene referencia al visor, use la inicialización escrita a mano anterior cuando su página necesite su propia barra de herramientas.
Cerrar el documento
Llame a objViewer.Close(true) cuando el usuario abandone el visor o abra un reemplazo: se limpia el widget y se envía una solicitud de cierre a DocImage.axd. objViewer.Close() sin argumento solo limpia el widget. En el servidor, viewer.CloseDocument(token) elimina la sesión del documento de inmediato, libera sus recursos de renderizado y revoca el acceso de la sesión a sus páginas. La expiración deslizante eventualmente hace lo mismo, pero cerrar documentos grandes explícitamente libera memoria antes.
Ejecutarlo
Coloque un PDF en ~/files/Sample.pdf, inicie el sitio en IIS Express (F5 en Visual Studio) y abra la página que aloja el widget. La primera página se renderiza, con miniaturas a la izquierda. Si no lo hace, consulte Solución de problemas.
Qué obtienes sin una licencia
Una licencia faltante no genera una excepción. El visor se renderiza normalmente, pero cada página lleva una marca de agua de evaluación. Consulte Configuración de licencia para saber dónde Doconut busca su licencia.
¿Fue útil esta página?