从经典 .NET 6 集成迁移
将现有 Doconut.NET6 应用迁移到当前 DI 和异步 API
Doconut 有两种不同的 .NET 6 集成方式。它们可以使用相同的 Doconut.NET6 包名,因此在更改包、启动、许可证或浏览器资源之前,请根据应用程序中的 API 确定所使用的代际版本。
您正在使用哪种 .NET 6 集成?
| 如果项目包含… | 代际 |
|---|---|
app.MapWhen(... "DocImage.axd" ...) | 传统 / 经典 |
new Viewer(_cache, _accessor, ...) | 传统 / 经典 |
Viewer.DoconutLicense(...) 或 Viewer.SetLicensePlugin(...) | 传统 / 经典 |
手动复制的 docViewer.js、documentLinks.js 或 docViewer.UI.js | 传统 / 经典 |
builder.Services.AddDoconut(...) | 当前集成 |
app.UseDoconutResources() 加 app.UseDoconut() | 当前集成 |
通过依赖注入提供的 Viewer | 当前集成 |
await viewer.OpenDocumentAsync(...) | 当前集成 |
如果同一应用程序中出现两个列的情况,则视迁移为不完整。不要通过资源或中间件使用另一代的文档令牌。
为什么 NuGet 包名可能无法告诉您
两个代际都以 Doconut.NET6 包 ID 发布。因此,包引用、锁文件或缓存的 .nupkg 本身并不能识别所使用的宿主 API。请记录确切的包版本,并一起检查 Program.cs、Viewer 构造、文档打开以及浏览器脚本。
当前本指南审计的发布版本是 Doconut.NET6 26.7.0。其可选的公共包为 Doconut.NET6.Converter 和 Doconut.NET6.Dicom,与核心包保持相同的发布版本。
迁移前准备
- 创建一个分支并对现有应用进行可部署的备份。
- 记录确切的核心和插件包版本。
- 清点每一个
DocImage.axd映射、new Viewer(...)调用、许可证加载调用、复制的 Doconut 脚本、自定义工具栏操作以及文档打开端点。 - 将当前的
.lic文件和部署机密保存在源码控制之外。 - 捕获一套具有代表性的 PDF、Office、图片、CAD、电子邮件、DICOM、可搜索、受密码保护以及带注释的文档。
- 记录现有的会话超时、安全行为、字体和平台设置。
在更改生产环境之前,先在一个环境中完成迁移。当前集成会更改服务生命周期、请求路由、会话所有权以及客户端资源交付方式。
包和许可证兼容性
有意识地替换或更新核心包;不要依赖相同的包 ID 自动选择新 API。默认命令会安装最新的稳定版:
dotnet add package Doconut.NET6若要进行可复现的迁移并使用本指南审计的发布版本,请将版本号作为单独的选项传入:
dotnet add package Doconut.NET6 --version 26.7.0保持每个 Doconut 插件的版本与核心包相同。当前集成在 AddDoconut() 时一次性加载许可证,使用以下优先级:
LicenseStream > LicenseContent > LicensePath > automatic discovery自动发现会查找 Doconut.Viewer.lic 以及伴随的 Doconut.Viewer.<Capability>.lic 文件。传统的 Viewer.DoconutLicense(...) 或 Viewer.SetLicensePlugin(...) 调用已不是当前的启动机制。请将许可证移动到 DoconutOptions,在使用自动发现时保持伴随文件一起,修改许可证后重新启动,并通过 IDoconutLicenseService 验证功能。
不要假设旧插件许可证的存在即意味着对当前插件构建的授权。请分别使用已批准的发布制品测试 Viewer、Search、Annotation、Converter 和 DICOM。
启动和依赖注入
传统应用使用 ASP.NET 缓存和请求访问器依赖来构造 Viewer:
// Classic integration — contrast only; do not compile this against the current SDK.
var viewer = new Viewer(_cache, _accessor, licenseFilePath);当前集成只需一次性注册 Doconut,并通过依赖注入获取 Viewer:
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.UnsafeMode = false;
});
builder.Services.AddSession();
app.UseSession();
app.UseDoconutResources();
app.UseDoconut();Viewer 是瞬态服务。文档会话管理器及其缓存拥有更长生命周期的文档状态,而不是特定的注入 Viewer 实例。
中间件和资源路由
删除检测 DocImage.axd 的传统 MapWhen 分支:
// Classic integration — remove during the cutover.
app.MapWhen(
context => context.Request.Path.ToString().EndsWith("DocImage.axd"),
branch => branch.UseDoconut(new DoconutOptions()));在当前管道中:
- 在启用会话安全的情况下,先调用
UseSession()再使用 Doconut; - 在
UseDoconut()之前调用UseDoconutResources(); - 保持
ResourcesPath、生成的资源 URL 与客户端ResPath对齐; - 当将
UseDoconut()映射到分支时,保持该分支和客户端BasePath对齐。
MiddlewarePath 是已验证的配置项,本身不会创建 ASP.NET Core 分支。可以使用上面编译示例中的简易管道,或使用显式的 app.Map("/doconut", branch => branch.UseDoconut()) 布局——这在客户端中是一致的做法。
Viewer 构造和生命周期
删除应用拥有的 Viewer 对象缓存。将 Viewer 注入到端点、Razor 页面、控制器或作用域的应用服务中:
app.MapPost("/api/open", async (Viewer viewer) =>
{
var token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
return Results.Ok(new { token });
});返回的令牌标识服务器端的文档会话。将其视为持有者凭证:不要记录、持久化或放入分析系统。
打开和关闭文档
用 OpenDocumentAsync(...) 替代同步的 OpenDocument(...):
// Current .NET 6 integration: Viewer comes from DI and document opening is asynchronous.
var token = await viewer.OpenDocumentAsync(path, new PdfConfig { AllowSearch = true });当前的重载接受文件路径或流、可选的格式配置、可选的 DocOptions,以及取消令牌。浏览器不再需要文档时,请显式关闭服务器会话:
viewer.CloseDocument(token);切换后不要复用传统令牌。请通过当前 API 再次打开每个文档。
配置类
当前 API 将关注点分离:
| 关注点 | 当前类型 |
|---|---|
| 中间件路径、授权、插件注册 | DoconutOptions |
| 密码、超时、安全性、水印 | DocOptions |
| 格式渲染和 DPI | PdfConfig、WordConfig、ExcelConfig 以及其他 BaseConfig 类型 |
| 浏览器小部件默认值 | ViewerConfig 或等价的 JavaScript 选项 |
| 生成的 CSS 与脚本 | CssConfig 与 ScriptConfig |
不要继续使用 DocOptions.ImageResolution 作为渲染控制。它已废弃,请在特定格式的配置上设置 BaseConfig.ImageResolution。请审查所有默认值,而不是假设传统配置具有相同行为。
Viewer 工具栏、搜索和注释
不要逐个迁移旧脚本。当前的参考应用会组合成一个完整的页面包:
- 使用
ReferenceCss输出 Viewer CSS 与已授权的 Search/Annotation CSS; - 渲染应用拥有的 Viewer 工具栏;
- 渲染
searchBarMount、annBarMount与必需的 Viewer 挂载点; - 使用
ReferenceScripts输出 Viewer 与已授权的模块脚本; - 加载应用自己的
viewerToolbar.js; - 初始化一个
objViewer; - 初始化已授权的 Search 与 Annotation 功能区;
- 对每个功能区调用
attach(objViewer); - 打开文档并调用
objViewer.View(token)。
搜索和注释是附加到同一个 Viewer 的模块,而不是独立的工具栏。主工具栏属于宿主应用;搜索和注释功能区是嵌入式、受功能门控的资源。
仅在当前页面能够使用 ReferenceCss 与 ReferenceScripts 发出的资源后,才删除手动复制的传统文件(如 documentLinks.js、docViewer.UI.js)。
插件注册
传统的静态插件许可证方法不会注册当前插件。请显式安装并注册每个已发布的包:
builder.Services.AddDoconut(options =>
{
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
options.AddPlugin<Doconut.Plugins.Dicom.DicomPlugin>();
});AddDoconut() 会在启动时验证已注册插件的功能。Converter 与 DICOM 是已发布的 .NET 6 插件。普通的 Search 与 Annotation 是内置的授权功能,而非 AddPlugin<TPlugin>() 包。
会话和文档安全
当前集成将文档绑定到不透明令牌和缓存会话。使用默认的 UnsafeMode = false 时,UseDoconut() 会添加文档访问安全性,宿主必须配置 ASP.NET 会话:
builder.Services.AddSession();
app.UseSession();保持 DocOptions.IsSecured = true,除非经过审查的设计另有要求。切勿将 UnsafeMode = true 作为迁移的捷径。请测试以下情况:无令牌、令牌格式错误、令牌已过期以及来自不同浏览器会话的令牌。
分布式参考应用会添加访问票据和传输细节。这些 API 对普通单节点迁移并非必需。
测试迁移
至少验证以下内容:
- 使用生产许可证和所有已注册插件的应用启动;
- Viewer CSS/脚本以及所有页面图片请求在选定路径下均能正常返回;
- 文档打开、导航、缩放、缩略图、打印以及显式关闭功能;
- 对包含文本的文档进行搜索,以及对仅图片文件的不可搜索状态;
- 注释的加载、保存、导出以及功能门控;
- Converter 的目标发现、输出、下载以及水印状态;
- DICOM 页面、帧和动画;.NET 6 技术元数据不可用;
- 受密码保护的文档、自定义字体、非拉丁文字以及配置的超时;
- 跨会话令牌拒绝和会话过期行为;
- 移动端、暗色模式以及生产环境的反向代理路径。
回滚计划
保留传统部署产物、匹配的包、许可证文件以及复制的浏览器资源。安全的回滚会切换整个应用代际,而不是将传统服务器与当前脚本混用,或将当前服务器与传统 DocImage.axd 调用混用。
在切换前,记录以下内容:
- 用于回滚的部署槽或产物;
- 数据库/缓存的影响(如果有);
- 如何使活动文档会话失效;
- 用于决定回滚的健康检查和冒烟文档;
- 谁可以恢复先前的包集合和配置。
旧版文档
已翻译的传统手册仍可在 旧版 .NET 6 设置 查看。新的 经典集成网关 解释相同的识别信号并链接回本迁移指南。
请在仍有传统安装的情况下,将历史 URL 保存在书签和支持工单中。它记录的是不同的代际,不会重定向到当前 API。
此页面有帮助吗?