从经典 .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() plus app.UseDoconut() | 当前集成 |
通过依赖注入提供的 Viewer | 当前集成 |
await viewer.OpenDocumentAsync(...) | 当前集成 |
如果同一应用程序中出现了两个列的情况,则视迁移为不完整。不要在资源或中间件中使用来自另一代际的文档令牌。
为什么 NuGet 包名可能无法告诉您
这两个代际都使用 Doconut.NET6 包标识发布。因此,仅凭包引用、锁文件或缓存的 .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()));在当前管道中:
- 在启用会话安全时,在 Doconut 之前调用
UseSession(); - 在
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 });
});返回的 token 标识服务器端文档会话。将其视为持有者凭证:不要记录、持久化或用于分析。
打开和关闭文档
将同步的 OpenDocument(...) 替换为 OpenDocumentAsync(...):
// 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);切换后不要复用传统 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)。
Search 和 Annotation 是附加到同一 Viewer 的模块,而不是独立的工具栏。主工具栏属于宿主应用程序;Search 和 Annotation 功能区是嵌入式、受功能限制的资源。
仅在当前页面能够使用 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 插件。普通搜索和注释是内置的许可功能,而不是 AddPlugin<TPlugin>() 包。
会话和文档安全
当前集成将文档绑定到不透明令牌和缓存会话。使用默认的 UnsafeMode = false,UseDoconut() 添加文档访问安全性,主机必须配置 ASP.NET 会话:
builder.Services.AddSession();
app.UseSession();除非经审查的设计另有要求,否则保持 DocOptions.IsSecured = true。切勿将 UnsafeMode = true 用作迁移捷径。请测试没有令牌、令牌格式错误、令牌已过期以及来自不同浏览器会话的令牌的请求。
Distributed 参考应用程序添加了访问票据和传输细节。这些 API 对于普通单节点迁移不是必需的。
测试迁移
至少,需要验证:
- 应用程序使用生产许可证和所有已注册插件启动;
- Viewer 的 CSS/脚本以及所选路径下的所有页面图像请求;
- 文档打开、导航、缩放、缩略图、打印以及显式关闭;
- 在包含文本的文档上进行搜索,以及仅图像文件的不可搜索状态;
- 注释的加载、保存、导出以及功能门控;
- Converter 目标发现、输出、下载以及水印状态;
- DICOM 页面、帧和动画;.NET 6 技术元数据不可用;
- 带密码保护的文档、自定义字体、非拉丁文字以及配置的超时;
- 跨会话令牌拒绝和会话过期行为;
- 移动端、暗模式以及生产环境的反向代理路径。
回滚计划
保持经典部署产物、匹配的包、许可证文件和复制的浏览器资源在一起。安全的回滚会切换整个应用程序代代,而不会将经典服务器与当前脚本混合,也不会将当前服务器与经典的 DocImage.axd 调用混合。
在切换之前,记录:
- 用于回滚的部署槽或产物;
- 数据库/缓存的影响(如果有);
- 活动文档会话将如何失效;
- 用于决定回滚的健康检查和冒烟文档;
- 谁可以恢复之前的包集合和配置。
旧版文档
已翻译的经典手册仍可在 Legacy .NET 6 setup 查看。新的 Classic integration gateway 解释相同的识别信号并链接回本迁移指南。
在经典安装仍然存在期间,请在书签和支持工单中保留该历史 URL。它记录了不同的代代,并未重定向到当前 API。
此页面对您有帮助吗?