快速入门
在 MVC 5 或 Web Forms 中渲染您的第一个文档
本指南将一个基于 .NET Framework 4.7.2 的 ASP.NET 应用程序从已安装的包转化为在浏览器中渲染的文档:Global.asax、一个打开端点、查看器的资源、小部件以及连接它们的令牌。它假设已完成来自安装的 Web.config 注册——如果没有 DocImage.axd 处理程序和资源模块,下面的内容将无法访问服务器。
在 Global.asax 中组合 Doconut
MVC 5 应用程序的完整 Application_Start 如下:
// 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.RegisterProvider使某些文档格式使用的旧版代码页对进程可用。请在首次打开文档之前调用一次。UnsafeMode = false是默认设置,显式写出以防止有人意外更改:DocImage.axd只向打开文档的 ASP.NET 会话提供页面。- 两个
IgnoreRoute调用 将 MVC 路由排除在DocImage.axd和/doconut-res/*之外,这些由处理程序和模块提供服务。Web Forms 应用程序没有 MVC 路由,因此不需要这两行。 DoconutHost.Shutdown在应用程序池回收时停止 Doconut 的后台工作并释放其服务。即使从未运行Initialize,调用它也是安全的。
打开文档
打开文档会返回一个不透明的令牌。小部件在每个页面请求中都会发送该令牌。
在 MVC 5 中,控制器操作从 DoconutHost.Services 中解析 Viewer 服务——MVC 5 不支持构造函数注入:
// 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 });
}文档必须在具有会话状态的请求内部打开,因为打开文档会授予当前 ASP.NET 会话访问其页面的权限。MVC 控制器和 Web Forms 页面默认拥有会话状态。自定义 IHttpHandler 没有会话状态,除非实现 System.Web.SessionState.IRequiresSessionState。如果在没有会话状态的处理程序中打开文档,查看器将在每个页面上显示 “您未被授权查看此页面。”。
在 Web Forms 中,页面本身可以在其代码隐藏文件中打开文档。OpenDocument 是 OpenDocumentAsync 的同步形式,适用于不使用异步页面的代码隐藏文件:
// 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"));
}将令牌视为持有者凭证:切勿记录或持久化它;仅交给小部件使用。当文档会话过期时,它将失效——请重新打开文档以获取新的令牌。
引用查看器资源
Viewer.ReferenceCss 和 Viewer.ReferenceScripts 会按依赖顺序发出指向 /doconut-res/ 的 <link> 和 <script> 标签,用于嵌入的资源。该小部件是 jQuery 插件,所以 jQuery 必须先加载。
MVC 5。 视图没有 @inject,因此在控制器中生成标签并通过 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)把这段工作放在控制器中。MVC 5 在首次请求时编译视图,如果没有额外的编译器包,编译器只能理解 C# 5 —— 不支持 ?.、不支持 $"..."、不支持 nameof。在 Visual Studio 中使用这些特性的视图可以正常编译,但在浏览器中会返回空的 500 错误。
Web Forms。 在代码隐藏文件中暴露相同的字符串,并使用 <%= %> 输出:
<head>
<%= ViewerCss %>
</head>
<body>
...
<%= ViewerScripts %>
</body>IncludeViewerCss 和 IncludeViewerScripts 是必需的核心。若要添加搜索和批注功能区,还需设置 IncludeSearchCss、IncludeAnnotationCss、IncludeSearchScripts、IncludeSearchBar、IncludeAnnotationScripts 和 IncludeAnnotationBar。当许可证未授予相应功能时,这两种方法都会省略对应功能区的文件;查看器本身仍然会启动。
将查看器添加到页面
渲染区域是两个嵌套的 div:
<div id="divDocViewer">
<div id="div_ctlDoc"></div>
</div>为外层 div 设置真实的高度 —— 查看器会填满其容器并在启动时测量它。查看器本身不绘制工具栏:GotoPage、Next、Zoom、FitType 等方法需要页面自行绑定到自己的按钮,这些按钮放在查看器旁边:
<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>初始化查看器并显示文档
在加载查看器脚本后,创建小部件并传入令牌:
var objViewer = $('#div_ctlDoc').docViewer({
showThumbs: true,
autoLoad: false,
pageZoom: 100,
FitType: 'width',
BasePath: '/', // '/' 表示站点根目录下的 DocImage.axd
ResPath: 'doconut-res/images', // 不带前导 '/'
onViewerReady: function () {
// 页面已可见;此处隐藏加载指示器
},
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); });在 Web Forms 中,如果页面本身打开文档,则最后三行改为 objViewer.View('<%= Token %>');。
以下四个细节若处理不当会导致失败且没有错误提示:
BasePath: '/'指向站点根目录下的DocImage.axd。如果应用部署在虚拟目录中,需要使用不带斜杠的目录名(例如'myapp',请求/myapp/DocImage.axd)。带前导斜杠('/myapp')会生成//myapp/DocImage.axd,浏览器会将其解释为对另一个主机的请求。ResPath: 'doconut-res/images'—— 图标位于资源根目录的下一级文件夹。使用'doconut-res'时,每个图标都会返回 404:工具栏图标和加载指示器消失,但文档本身仍会渲染。前导斜杠会导致同BasePath一样的错误。- 回调是选项。
onViewerReady、onError等必须写在传给docViewer(...)的对象里。像ctlDoc_ViewerReady这样的全局函数不会被调用。 - 先保留查看器实例,再单独调用
View。docViewer(...)返回包含Zoom、Next、FitType等方法的对象;View(...)返回其他东西。写成var objViewer = $('#div_ctlDoc').docViewer({...}).View(token)会渲染文档,但随后第一次点击工具栏时会出现objViewer.Zoom is not a function错误。
选项名称混用了 camelCase(showThumbs、autoLoad、pageZoom)和 PascalCase(FitType、BasePath、ResPath)。拼写错误的选项会被忽略,组件会使用默认值。
单行替代方案
对于只需要显示文档且不需要自定义工具栏的页面,Viewer.RenderViewer 会生成完整的初始化脚本——docViewer(...),其中 BasePath: '/' 和 ResPath: 'doconut-res/images',随后调用 .View(token)。该功能仅在此包中提供:
// Web Forms code-behind, after opening the document
ViewerInit = viewer.RenderViewer("div_ctlDoc", Token);<div id="div_ctlDoc" style="height: 100vh"></div>
<%= ViewerScripts %>
<%= ViewerInit %>将 ViewerConfig 作为第三个参数传入,可更改缩放、适配方式或缩略图面板。由于生成的脚本不保留对查看器的引用,当页面需要自己的工具栏时,请使用上述手写的初始化代码。
关闭文档
当用户离开查看器或打开替代文档时,调用 objViewer.Close(true);它会清除部件并向 DocImage.axd 发送关闭请求。未传参的 objViewer.Close() 只会清除部件本身。在服务器端,viewer.CloseDocument(token) 会立即移除文档会话,释放渲染资源,并撤销会话对页面的访问。滑动过期最终也会产生相同效果,但显式关闭大型文档可以更快释放内存。
运行它
将 PDF 放置在 ~/files/Sample.pdf,在 IIS Express 中启动站点(在 Visual Studio 中按 F5),然后打开承载部件的页面。首个页面会渲染,并在左侧显示缩略图。如果未渲染,请参见故障排除。
未授权时的获取内容
缺少许可证不会抛出异常。查看器仍会正常渲染,但每页都会带有评估水印。有关 Doconut 查找许可证的位置,请参见许可证设置。
此页面对您有帮助吗?