迁移

Doconut.NETFramework 26.8.0 (.NET Framework 4.7) 到 26.9.0 (.NET Framework 4.7.2)

本文档介绍如何将现有的 ASP.NET 应用程序从 Doconut.NETFramework 26.8.0 或更早版本(.NET Framework 4.7)升级到 26.9.0 及以后版本(.NET Framework 4.7.2)。Doconut 示例包包含完整的迁移指南以及已移植到新 API 的经典示例——MVC 5、Web 农场和 Web Forms。将你的应用程序与它所基于的示例进行对比是最快的迁移路径。

一个包,两个版本

两个库使用相同的包标识符 Doconut.NETFramework。版本号用于区分它们:

版本目标API
26.8.0 及更早.NET Framework 4.7之前的 API
26.9.0 及以后.NET Framework 4.7.2新的 API

更新包即完成升级。没有单独的安装包,也没有兼容层:26.9.0 是不同的 API 表面,更新后会出现编译错误——请参阅本页后续内容。.NET Framework 4.7 系列已停止维护,26.8.0 是其最后一次发布。你可以继续使用它——这里没有任何安全修复会因此错过——但新版本、插件、分布式模式以及即插即用小部件仅在 26.9.0 及以后提供。

1. 重新定位并更新包

首先将 Web 项目重新定位到 .NET Framework 4.7.2:仍然定位到 4.7 的项目无法安装 26.9.0,NuGet 会拒绝更新。随后更新 Doconut.NETFramework 并添加你使用的插件包(Doconut.NETFramework.Converter、Doconut.NETFramework.Dicom,……)。每个插件都需要相应的授权许可。

如果项目使用 packages.config,更新过程会执行之前版本的卸载步骤,移除 DocImage 处理程序(位于 Web.config),而 26.9.0 并不会重新添加。请按照第 3 步重新注册;在此之前,DocImage.axd 会返回 404,页面无法渲染。

2. 命名空间:几乎所有内容都迁移到根命名空间

之前现在
using Doconut.Configs.View;using Doconut;
using Doconut.Models;using Doconut;
using Doconut.Configs;using Doconut;
using Doconut.Configs.Cloud;using Doconut.Clouds;
using Doconut.Configs.Conversion;unchanged

类型名称未变:WordConfig、PdfConfig、ExcelConfig、CssConfig、ScriptConfig、FileShareConfig 以及其余类型仍然存在。大多数文件只需删除 using 行即可完成迁移。

3. 启动:DoconutHost.Initialize 与两个 Web.config 条目

经典包在每次请求时构建查看器实例,选项作为该实例的属性。新包采用组合根模式,在 Application_Start 中构建一次,查看器则作为可解析的服务:

csharp
// 之前 - Doconut.NETFramework 26.8.0 及更早版本,按请求
var viewer = new Viewer
{
    ID = "ctlDoc",
    IncludeJQuery = true,
    BasePath = "/",
    FitType = "width"
};
csharp
// Doconut.NETFramework 26.9.0\u002B - 查看器从 DoconutHost 解析,许可证在 DoconutHost.Initialize() 中配置一次
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
var token  = await viewer.OpenDocumentAsync(path, new PdfConfig { AllowSearch = true });

DoconutHost.Initialize 放入 Application_Start,DoconutHost.Shutdown 放入 Application_End,并且 Web.config 获得 DocImage.axd 处理程序和资源模块——两者均在安装章节中。每页外观设置(FitType、FixedZoom、ShowHyperlinks,……)从查看器实例迁移到小部件的选项,或迁移到传递给 Viewer.RenderViewer 的 ViewerConfig(参见查看器配置)。new Viewer() 仍然在 DoconutHost.Initialize 运行后编译一次,因此迁移后的代码后置仍可保留该行,同时你可以移动设置。

安全性保持不变。 打开文档会授予当前 ASP.NET 会话访问其页面的权限,DocImage.axd 会拒绝其他所有请求。原先用于关闭此功能的 DoconutUnSafeMode 应用设置现在改为 options.UnsafeMode,位于 DoconutHost.Initialize——请保持其 false。详见会话与安全。

导致整个站点宕机的启动失败。 某个已注册插件的功能未获得授权时会在 Application_Start 抛出异常,随后应用对每个请求返回空的 500——没有错误页面,IIS 日志中也没有记录,仅在 Windows 事件日志(来源 ASP.NET)中留下条目。许可证从站点根目录下的 wwwroot 读取,其他位置不读取;且必须存在基础的 Doconut.Viewer.lic,否则插件旁边的许可证也不会被读取。详见许可证设置。

4. Web 农场:从标记到分布式模式

经典模型是 viewer.IsWebfarm = true 加 ExportToPng(path)。新模型只需注册一次:所有节点共享同一个存储和签名密钥,一个绑定到浏览器的已签名票据取代 “哪个节点响应”:

csharp
Doconut.DoconutHost.Initialize(
    options => options.UnsafeMode = false,
    services => services.AddDoconutDistributed(d =>
    {
        d.Store             = CloudLocation.FileShare;
        d.FileShareRootPath = @"\\fileserver\doconut-shared";   // WebfarmPath 是别名
        d.SigningKey        = farmKey;                           // >= 32 字节,在每个节点上相同
    }));

然后像往常一样打开文档,绑定浏览器(DocOptions.BrowserId = DoconutFarmBinding.EnsureBrowserId(...))并将 viewer.AccessToken 交给带有令牌的小部件。会话与安全 中有步骤说明;Web 农场 示例是完整的节点。IsWebfarm 和 WebfarmPath 仍然可以编译,但它们不再切换任何东西。

有两件看起来像成功却并非如此的事:DistributedDocumentPublisher.PublishAsync 会写入文档的渲染文件但不打开会话,所以指向已发布令牌的查看器会得到约 2 KB、状态码 200 的错误图片;没有 doconut-client Cookie 的测试客户端也会得到同样的图片,而不是 401。通过大小可以区分真实页面和错误图片。

5. 转换是插件,且体积更小

SourceFormatConverter 枚举、十二个 *ConfigConverter 类以及它们的嵌套目标枚举被一个枚举 ConversionTarget 和一次调用取代:

csharp
using System.IO;
using System.Threading;
using Doconut;
using Doconut.Configs.Conversion;

// 假设 DoconutHost 已经初始化,并且一个名为 ct 的 CancellationToken 可用。
var provider = DoconutHost.Services;
var converter = (DocumentConverter)provider.GetService(typeof(DocumentConverter));
Stream source = /* 你的输入流 */;
var result = await converter.ConvertAsync(source, ".dwg", ConversionTarget.Pdf, null, ct);

源格式来自你传入的扩展名。没有兼容层:每个 SourceFormatConverter 引用都会导致编译错误,你只能通过删除它来解决。按格式的选项对象未能保留——WordConfigConverter.HtmlOptions 和 CadConfigConverter.CadOptions.ShowColor 通过 ConvertAsync 没有等价实现。在 Web 表单 中,永远不要在 ConvertAsync 上阻塞——参见 转换插件。

6. 云存储:将其视为 共享文件夹

云配置类型保持不变,仍然移动到 Doconut.Clouds。然而云请求处理程序是 ASP.NET Core 组件,经典应用没有管道来运行它们。从 System.Web 站点出发,可将云存储视为 共享文件夹——在 Azure 上,即挂载到每个节点的 Azure Files 共享——通过 FileShareConfig 访问。

7. 客户端更改静默失败

下面的每一项都能编译、运行、没有日志输出,却做错了事:

之前现在
ResPath: 'doconut-res'ResPath: 'doconut-res/images' — 否则每个图标在文档渲染时都会返回 404
function ctlDoc_ViewerReady() { }docViewer({ onViewerReady: function () { } }) — 查看器回调现在是可选的
var viewer = $(el).docViewer({...}).View(token)先分配 docViewer(...),然后单独调用 viewer.View(token)
viewer.Refit() 以适应页面viewer.FitType('width') — Refit() 只重新计算布局
var n = viewer.Search(kw, exact)viewer.Search(kw, exact, function (n) { … }) — 计数在回调中到达
if (viewer.SaveAnnotations()) { … }docViewer({ onAnnSaved: …, onAnnSaveError: … })
function ctlDoc_Created() { } (annotations)未更改 — 注释事件函数仍然是全局的,按名称查找

另外还有三点:查看器不会绘制自己的工具栏(你的页面将 Zoom、Next、GotoPage 以及其余部分绑定到自己的按钮);在隐藏的 Bootstrap 模态框中创建的查看器尺寸为 0×0,直到为其容器显式设定高度并在 shown.bs.modal 上重新适配后才会绘制;并且 AllowSearch 对 PDF 默认使用 false,因此文档可以完美渲染,而每次搜索都返回空结果。

8. 什么消失了

已移除取而代之
DocumentSearch / TextSearch.cs无 — 搜索在格式查看器提取的文本上运行
Viewer.WatermarkInfo无等价项
WordConfigConverter.HtmlOptions没有通过 ConvertAsync 的选项对象
SourceFormatConverter,*ConfigConverter 类ConversionTarget 和 ConvertAsync
Doconut.Configs.Editor已移除
viewer.IsWebfarm + ExportToPng(path)AddDoconutDistributed 和普通打开

建议的工作顺序

  1. 重新定位,替换包,并使 Global.asax 在 DoconutHost.Initialize 和两个 Web.config 注册下编译成功。站点应当启动。
  2. 一个查看器页面:获取文档进行渲染,然后完成第 7 节,直到工具栏、搜索和注释正常工作。在真实浏览器中验证 — 该章节中没有任何错误抛出。
  3. 转换(第 5 节):机械式的,并且大多数编译错误。
  4. 其余页面,使用已移植的示例作为差异目标。
  5. Web 农场(第 4 节),如果你有的话。使用两个节点和浏览器,或保持 cookie 的客户端进行测试。

此页面对您有帮助吗?