转换插件
将文档转换为 45 种目标格式
Converter 插件将 Doconut 转变为文档转换服务。它提供公共 DocumentConverter 门面的引擎,并且(可选)提供一个带有自身 HTTP 合约的即插即用小部件,使您可以从 C#、从该小部件或从自行编写的前端进行文档转换。
安装包
安装最新的稳定版 Converter 插件:
dotnet add package Doconut.NETStandard.Converter要将插件固定到当前的 26.8.0 版本,请单独指定版本号:
dotnet add package Doconut.NETStandard.Converter --version 26.8.0保持 Converter 包的版本与 Doconut.NETStandard 相同。包 ID 为 Doconut.NETStandard.Converter;.26.8.0 只出现在下载的 .nupkg 文件名中。
注册插件
没有 AddConverter() 方法——Doconut 的插件模型是统一的。每个插件,包括 Converter,都是通过相同方式注册的:在 AddDoconut() 中调用 AddPlugin<TPlugin>()。ConverterPlugin 随其自己的 NuGet 包 Doconut.NETStandard.Converter 提供,安装在基础查看器包旁边。
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});如果缺少许可证、使用旧的
TRIAL文件,或使用未授予Converter功能的非临时许可证,此调用将在启动时抛出异常——在AddDoconut()内部抛出的InvalidOperationException,在应用处理请求之前。接受临时的 Demo/NFR 注册;在其日历到期后,转换仍可使用,但输出会带有水印。没有静默的免费层。请参阅 许可证设置 了解许可证的加载方式。
从 C# 转换
每次转换都会返回一个定位在 0 的可寻址 MemoryStream,可立即读取或复制。随时从依赖注入中解析 DocumentConverter——它本质上是无状态的,因此单个实例可以安全地在请求之间复用。
viewer.Converter.GetConverter() 在此不存在。转换不再通过 viewer 实例访问:请注入 Doconut.DocumentConverter。
// Inject DocumentConverter; its constructor is internal, so never `new` it.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);// sourceExtension includes the leading dot. password is null unless the document is protected.
Stream png = await converter.ConvertAsync(upload, ".xlsx", ConversionTarget.Png, password: null, ct: ct);Stream html = await converter.WordToHtmlAsync("report.docx", ct);Stream docx = await converter.HtmlToWordAsync(html, ConversionTarget.Docx, ct);有两个容易出错的细节:流重载中的 sourceExtension 必须包含前导点(例如 ".xlsx",而不是 "xlsx")——转换器会将其与格式目录匹配,缺少点的扩展名将无法解析。并且尽管名称中含有 WordToHtmlAsync,它返回的是 Task<Stream>,而不是 Task<string>——您会得到 HTML 文档(图像以 Base64 嵌入)作为流,这与其他所有转换结果相同。
目标格式
ConversionTarget(命名空间 Doconut.Configs.Conversion)包含 45 个成员:
Pdf, Docx, Doc, Html, Xlsx, Pptx, Png, Jpeg, Csv, Tiff, Bmp, Gif, Svg, Xml,
Txt, Xls, Jp2, Rtf, Odt, Ods, Odp, Epub, Xps, Webp, Msg, Eml, Emlx, Mhtml,
Xlsm, Xlsb, Ppt, Docm, Dot, Dotx, Dotm, Vsdx, Vssx, Vstx, Vsdm, Vssm, Vstm,
Vdx, Vsx, Vtx, Ico此枚举覆盖了所有源族。之前的库为每个族提供了单独的 *ConfigConverter 类型——WordConfigConverter、ExcelConfigConverter 等——每个都有自己的嵌套 EnTargetFormat 枚举,以及用于输入的 SourceFormatConverter 枚举。所有这些都已移除;请参阅 迁移指南。
并非每种源格式都能转换为每种目标格式——插件将每个源的格式族(Word、Excel、PowerPoint、PDF、CAD、图像、电子邮件、图表、项目/任务、PSD、网页文档)映射到其固定的允许目标集合。不要将此枚举硬编码为 UI 的目标列表:?convert=open 会返回刚上传文件的实际 allowedTargets,应以此来驱动选择器。
Drop-in 小部件
小部件的 ?convert=open|run|download 端点默认是可选且未启用 —— 默认安全。请在服务器端启用它们,并同时进行插件注册:
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
options.AddConverterWidget(widget =>
{
widget.MaxUploadMb = 25;
});
});<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) 的初始化选项:
| 选项 | 类型 | 默认值 | 备注 |
|---|---|---|---|
basePath | string | /doconut | ?convert= 端点的基础路径;必须与实际挂载 UseDoconut() 的 ASP.NET 分支相匹配(通常通过 MiddlewarePath 协调) |
resPath | string | /doconut-res | 为保持与其他 Doconut 小部件的配置一致性而接受;转换小部件目前并未基于它构建任何 URL |
maxUploadMb | number | 25 | 仅在客户端进行预检查 —— 在上传前拒绝超出大小的文件。服务器会独立强制其自身上限,若超出则返回 413 |
licenseUrl | string | null | null | 设置后,会将结果页面的水印提示转换为指向该 URL 的链接 |
labels | object | {} | 覆盖小部件的英文默认字符串的任意子集(拖拽文字、按钮、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() 返回小部件实例本身 —— 保存该实例以编程方式控制小部件:
const conv = Doconut.convert('#doconut-convert', { basePath: '/doconut' });
conv.reset(); // back to the idle/drop screen; does not re-fire onReady
conv.loadFile(file); // starts the flow with a File object; no-op unless currently idle
conv.destroy(); // removes listeners, empties the mount; the instance is unusable after this构建自己的前端
小部件只是此 HTTP 合约的客户端 —— 直接基于它构建自己的前端以获得不同的用户体验。所有三个路由都位于挂载 UseDoconut() 的 ASP.NET 分支下(通常是 /doconut):
| 路由 | 用途 | 成功响应 |
|---|---|---|
POST ?convert=open (multipart, field file) | 上传并打开源文档以进行预览 | 200 — { token, pages, sourceExt, allowedTargets } |
POST ?token=<token>&convert=run&target=<ext> | 将已存储的源转换为 target | 200 — { downloadToken, resultToken, resultPages, downloadName, watermarked } |
GET ?convert=download&token=<downloadToken> | 流式传输已转换的文件 | 200 — file bytes, Content-Disposition: attachment, Cache-Control: no-store |
上传的源字节会在服务器端存储,具有 30 分钟的 TTL;一旦该时间窗口过去,run 将返回 404,文件必须重新打开。转换后的结果也保存在同一存储中 —— 转换完成后,downloadToken 将获得新的 30 分钟有效期 —— 而 resultToken 是普通的查看器会话令牌,其生命周期遵循查看器的会话缓存,独立于存储。
open 响应中的 sourceExt 不带前导点(例如 "docx")—— 与 DocumentConverter.ConvertAsync 的 sourceExtension 参数要求带点的约定相反。
失败模式(按路由分组):
| 路由 | 状态码 | 何时 | 响应体 |
|---|---|---|---|
| any | 404 | 小部件未启用(从未调用 AddConverterWidget())—— 在任何三个路由分发前即检查 | 仅状态码 |
| any | 405 | HTTP 方法错误(open/run 需要 POST;download 需要 GET) | 仅状态码 |
open | 413 | 上传的文件超过 MaxUploadMb | { "error": "File is too large." } |
open | 400 | 没有 multipart 正文、没有文件,或源扩展名无法转换 | { "error": "..." } |
run | 400 | 令牌格式错误(不是 GUID),或 target 无法解析为 ConversionTarget | { "error": "Invalid token." } / { "error": "Unknown target format." } |
run | 400 | target 不在源的 allowedTargets 列表中 | { "error": "That target format is not available for this file." } |
run | 404 | 已存储的上传已过期(30 分钟 TTL)或令牌从未打开 | { "error": "Upload expired — please re-open the file." } |
open, run | 500 | 内部处理失败 | { "error": "<sanitized message>" } — 与其他 Doconut 错误路径相同的清理方式;永不泄露内部引擎名称 |
download | 400 | 令牌格式错误(不是 GUID) | 仅状态码 |
download | 404 | 未知或已过期的下载令牌 | 仅状态码 |
资源所有权
转换器返回一个可寻址的 MemoryStream,其位置为零。调用方拥有该流,并应在复制或返回其内容后进行释放。DocumentConverter 服务本身是无状态的,并通过依赖注入解析;不要手动构造或释放该服务。
对于网页小部件,上传和下载的缓存各自拥有独立的 30 分钟 TTL。查看器的 resultToken 则遵循查看器会话的生命周期。关闭查看器结果不会删除仍然有效的下载缓存,重置浏览器小部件也不会延长任一 TTL。
故障排除
| 症状 | 检查 |
|---|---|
解析 DocumentConverter 失败 | ConverterPlugin 注册发生在 AddDoconut() 内部 |
| 应用程序在启动期间失败 | 加载的许可证授予 Converter |
| 流转换提示格式不受支持 | sourceExtension 包含前导点 |
| 小部件 JavaScript 加载成功,但请求返回 404 | AddConverterWidget() 未被调用 |
| 小部件请求使用了错误的 URL | basePath 与映射 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 字段。可以在购买前使用评估许可证构建并端到端测试集成——唯一变化的是输出字节。
此页面对您有帮助吗?