转换器插件

将文档转换为 24 种目标格式

Converter 插件将 Doconut 转变为文档转换服务。它提供了公共 DocumentConverter 门面的引擎,并且(可选)提供了一个带有自身 HTTP 合约的即插即用小部件,使您可以从 C#、从该小部件或从您自行编写的前端进行文档转换。

安装包

安装最新的稳定版 Converter 插件:

bash
dotnet add package Doconut.NET6.Converter

要将插件固定在当前 26.7.0 版本,请单独传入版本号:

bash
dotnet add package Doconut.NET6.Converter --version 26.7.0

保持 Converter 包与 Doconut.NET6 使用相同的版本。包 ID 为 Doconut.NET6.Converter;.26.7.0 仅出现在下载的 .nupkg 文件名中。

注册插件

没有 AddConverter() 方法——Doconut 的插件模型是统一的。每个插件,包括 Converter,都是以相同方式注册的:在 AddDoconut() 中调用 AddPlugin<TPlugin>()。ConverterPlugin 随其自身的 NuGet 包 Doconut.NET6.Converter 一起提供,安装在基础查看器包旁边。

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
    options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});

此调用在启动时会因缺少许可证、旧的 TRIAL 文件,或不具备授予 Converter 能力的非临时许可证而抛出异常——在 AddDoconut() 内部抛出的 InvalidOperationException,在应用处理请求之前。接受临时的演示/NFR 注册;在其日历到期后,转换仍可使用,但输出会带有水印。没有静默的免费层。请参阅许可证设置了解许可证的加载方式。

从 C# 转换

每次转换都会返回一个定位在 0 的可查找 MemoryStream,可立即读取或复制。从 DI 中解析 DocumentConverter,无论何处需要——它本质上是无状态的,因此单个实例在请求之间安全复用。

csharp
// 注入 DocumentConverter;其构造函数是 internal 的,因此永远不要 `new` 它。
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);
csharp
// sourceExtension 包含前导点。除非文档受保护,否则 password 为 null。
Stream png = await converter.ConvertAsync(upload, ".xlsx", ConversionTarget.Png, password: null, ct: ct);
csharp
Stream html = await converter.WordToHtmlAsync("report.docx", ct);
csharp
Stream docx = await converter.HtmlToWordAsync(html, ConversionTarget.Docx, ct);

两个容易出错的细节:流重载上的 sourceExtension 必须包含前导点(".xlsx",而不是 "xlsx")——转换器会将其与格式目录匹配,单独的扩展名无法解析。并且尽管名字如此,WordToHtmlAsync 返回的是 Task<Stream>,而不是 Task<string>——您会得到 HTML 文档(图像以 Base64 嵌入)作为流,这与其他所有转换结果相同。

目标格式

text
Pdf, Docx, Doc, Html, Xlsx, Pptx, Png, Jpeg, Csv, Tiff, Bmp, Gif, Svg, Xml,
Txt, Xls, Jp2, Rtf, Odt, Ods, Odp, Epub, Xps, Webp

并非所有源文件都能转换为所有目标——插件将每种源的格式族(Word、Excel、PowerPoint、PDF、CAD、Image、Email、Diagram、Project/Task、PSD、web document)映射到其固定的允许目标集合。不要在 UI 的目标列表中硬编码此枚举:?convert=open 返回刚上传的文件对应的实际 allowedTargets,这才应该用于驱动选择器。

即插即用小部件

小部件的 ?convert=open|run|download 端点是可选择加入的,默认情况下被禁用——默认安全。
在服务器端启用它们,同时进行插件注册:

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
    options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
    options.AddConverterWidget(widget =>
    {
        widget.MaxUploadMb = 25;
    });
});
html
<div id="doconut-convert"></div>
<script src="/doconut-res/js/doconutConverter.js"></script>
<script>
  Doconut.convert('#doconut-convert', { basePath: '/doconut', resPath: '/doconut-res', maxUploadMb: 25 });
</script>

如果没有 AddConverterWidget(),这三个 ?convert= 端点会返回 404 ——但 JS 文件本身仍然会被提供(它是一个普通的嵌入式静态资源;只有它所调用的端点受到限制)。AddConverterWidget() 仍然需要注册 Converter 插件并拥有授予 Converter 的许可证——它本身并不授予转换权限。

自定义小部件

传递给 Doconut.convert(selector, options) 的初始化选项:

选项类型默认值备注
basePathstring/doconut?convert= 端点的基础路径;它必须匹配实际挂载 UseDoconut() 的 ASP.NET 分支(通常通过 MiddlewarePath 协调)
resPathstring/doconut-res为与其他 Doconut 小部件的配置保持一致而接受;转换器小部件目前不会基于它构建任何 URL
maxUploadMbnumber25仅客户端预检查——在上传前拒绝超大文件。服务器独立强制其自身上限,若超出则返回 413
licenseUrlstring | nullnull设置后,将结果屏幕上的水印提示转换为指向此 URL 的链接
labelsobject{}覆盖小部件的任意子集的英文默认字符串(拖拽文本、按钮、aria-live 通知、错误信息)

回调:

回调触发时机负载
onReady()小部件已渲染其空闲/拖拽屏幕—
onSourceLoaded({ token, pages, sourceExt, allowedTargets })?convert=open 成功时源会话令牌、页数、源扩展名(无前导点)、允许的目标列表
onConverted({ downloadToken, resultToken, resultPages, downloadName, watermarked, target })?convert=run 成功时与运行响应相同的字段,加上请求的 target
onDownload({ downloadName, downloadToken })用户点击下载链接时与浏览器的原生下载同时触发——它不会拦截或替代下载
onError({ phase, message })打开或运行请求失败时phase 为 'open' 或 'run';message 为已清理的服务器错误(或上传大小预检查的客户端消息)

Doconut.convert() 返回小部件实例本身——保留它以编程方式驱动小部件:

javascript
const conv = Doconut.convert('#doconut-convert', { basePath: '/doconut' });
conv.reset();         // 返回空闲/掉落屏幕;不会重新触发 onReady
conv.loadFile(file);  // 使用 File 对象启动流程;除非当前为空闲状态,否则不执行任何操作
conv.destroy();       // 移除监听器,清空挂载点;实例在此之后不可使用

构建自己的前端

小部件只是此 HTTP 合约的客户端——直接针对它构建自己的前端以获得不同的用户体验。所有三个路由都位于挂载 UseDoconut() 的 ASP.NET 分支下(通常为 /doconut):

路由用途成功响应
POST ?convert=open (multipart, field file)上传并打开源文档以进行预览200 — { token, pages, sourceExt, allowedTargets }
POST ?token=<token>&convert=run&target=<ext>将暂存的源转换为 target200 — { downloadToken, resultToken, resultPages, downloadName, watermarked }
GET ?convert=download&token=<downloadToken>流式传输已转换的文件200 — file bytes, Content-Disposition: attachment, Cache-Control: no-store

上传的源字节在服务器端暂存,TTL 为 30 分钟;一旦该窗口过期,run 将返回 404,文件必须重新打开。转换后的结果仍保存在同一暂存区——转换完成后,downloadToken 将获得其自己的全新 30 分钟窗口——而 resultToken 是普通的查看器会话令牌,其生命周期遵循查看器的会话缓存,独立于暂存区。

sourceExt 在 open 响应中没有前导点(例如 "docx")——这与 DocumentConverter.ConvertAsync 上的 sourceExtension 参数的约定相反,后者需要前导点。

失败模式,按路由分组:

路由状态何时主体
任意404小部件未启用(AddConverterWidget() 从未被调用)——在任何三个路由分发之前检查仅状态
任意405HTTP 方法错误(open/run 需要 POST;download 需要 GET)仅状态
open413上传的文件超过 MaxUploadMb{ "error": "File is too large." }
open400没有 multipart 正文、没有文件,或源扩展名无法转换{ "error": "..." }
run400令牌格式错误(非 GUID),或 target 无法解析为 ConversionTarget{ "error": "Invalid token." } / { "error": "Unknown target format." }
run400target 不在源的 allowedTargets 中{ "error": "That target format is not available for this file." }
run404暂存的上传已过期(30 分钟 TTL)或令牌从未被打开{ "error": "Upload expired — please re-open the file." }
open, run500内部处理失败{ "error": "<sanitized message>" } — 以与其他所有 Doconut 错误路径相同的方式清理;永不泄露内部引擎名称
download400令牌格式错误(非 GUID)仅状态
download404未知或已过期的下载令牌仅状态

资源所有权

转换器返回一个定位在零位置的可寻址 MemoryStream。调用方拥有该流,并应在复制或返回其内容后进行释放。DocumentConverter 服务本身是无状态的,并通过依赖注入解析;不要手动构造或释放该服务。

对于网页小部件,上传和下载缓存各自拥有独立的 30 分钟 TTL。相反,查看器 resultToken 遵循查看器会话的生命周期。关闭查看器结果不会删除仍然有效的下载缓存,重置浏览器小部件也不会延长任一 TTL。

故障排除

症状检查
解析 DocumentConverter 失败ConverterPlugin 注册发生在 AddDoconut() 内
应用程序在启动期间失败加载的许可证授予 Converter
流转换提示格式不受支持sourceExtension 包含前导点
小部件 JavaScript 加载但请求返回 404AddConverterWidget() 未被调用
小部件请求使用了错误的 URLbasePath 与映射了 UseDoconut() 的分支匹配
目标缺失使用 convert=open 返回的 allowedTargets;并非每个源都支持每个枚举目标
下载已过期重复 convert=open/convert=run;缓存令牌是有意临时的

水印

注册了 ConverterPlugin 后,主机的许可证处于以下三种状态之一:

许可证状态启动门槛转换输出
付费查看器许可证授予 Converter,在其有效期内通过干净 — watermarked: false
活跃的评估(演示/NFR)许可证通过成功转换,带有评估水印 — watermarked: true
未授权的、遗留的 TRIAL 文件,或不授予 Converter 的非临时许可证应用程序永不启动 — 如上所述的启动门槛会抛出异常—
已过期的临时/演示许可证注册在过期后仍然有效带有评估水印转换 — watermarked: true

两个调用路径都依据相同的规则计算该标志:DocumentConverter C# 门面内部从许可证的 IsViewerLicensed 和 IsTemporary 状态派生出它,且小部件的 ?convert=run 处理程序进行等效检查(IsViewerLicensed && !IsTrial && !IsTemporary)以填充它返回的 watermarked 字段。在购买前,可在评估许可证上构建并端到端测试集成——仅输出字节会变化。

此页面对您有帮助吗?