转换插件

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

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

安装包

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

bash
dotnet add package Doconut.NET8.Converter

要将插件固定到当前的 26.7.0 版本,请单独传递版本号:

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

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

注册插件

没有 AddConverter() 方法——Doconut 的插件模型是统一的。每个插件,包括 Converter,都是以相同方式注册的:在 AddDoconut() 中调用 AddPlugin<TPlugin>()。ConverterPlugin 以其自己的 NuGet 包 Doconut.NET8.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 文档)映射到其固定的允许目标集合。不要将此枚举硬编码为 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 ——但 JavaScript 文件本身仍会被提供(它是普通的嵌入式静态资源;只有它所调用的端点受到限制)。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 — 文件字节, 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 字段。在购买前,可以在评估许可证上构建并端到端测试集成——仅输出字节会变化。

此页面对您有帮助吗?