PowGrade.FileConverters.DocxToPdf 0.1.0

dotnet add package PowGrade.FileConverters.DocxToPdf --version 0.1.0
                    
NuGet\Install-Package PowGrade.FileConverters.DocxToPdf -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PowGrade.FileConverters.DocxToPdf" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PowGrade.FileConverters.DocxToPdf" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="PowGrade.FileConverters.DocxToPdf" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PowGrade.FileConverters.DocxToPdf --version 0.1.0
                    
#r "nuget: PowGrade.FileConverters.DocxToPdf, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PowGrade.FileConverters.DocxToPdf@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PowGrade.FileConverters.DocxToPdf&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=PowGrade.FileConverters.DocxToPdf&version=0.1.0
                    
Install as a Cake Tool

DocxToPdf(DOCX 转 PDF)

高性能、可扩展的 .NET 10 文档转换库与 CLI,用自研 PDF 引擎(SkiaSharp 驱动)将 DOCX 高保真转换为 PDF,支持 PDF/A、数字签名、目录页、页眉页脚、脚注尾注、多栏排版、字段解析等企业级能力。

功能概览

  • 文档元素:段落、列表、表格、图片、超链接、书签、页眉/页脚、脚注/尾注、页面边框、多栏、横竖排、首字下沉
  • 高级样式:完整样式继承、系统/嵌入/CJK 字体、主题色、VML 形状、DrawingML 文本提取与格式保留
  • 图形图表:柱/条、折线、饼图、面积、散点、雷达、圆环、股票、气泡、曲面、组合图;SmartArt 栅格化渲染、未知布局基于 layout hint 的自适应 generic placement/connector/text-box sizing/shape routing(已覆盖 relationship、balance、converging、diverging、target、alternating、stacked、timeline、funnel 等弱分类族),并尽量保留可提取文本
  • 数学公式:OMML 渲染;分数、上下标、根号、矩阵等布局
  • 字段系统:PAGE/NUMPAGES(双遍延迟)、DATE/TIME、AUTHOR/TITLE/SUBJECT、FILENAME/FILEPATH、DOCVARIABLE、MERGEFIELD、HYPERLINK、REF/PAGEREF、TOC、IF/COMPARE、LISTNUM、SYMBOL、SECTION/SECTIONPAGES、EQ、SET/ASK/FILLIN、USERNAME/USERINITIALS、MERGEREC/MERGESEQ、BARCODE、AUTOTEXT
  • PDF 能力:加密与权限、PDF/A(1a/1b/2a/2b/2u/3a/3b/3u/4/4e/4f)、ICC/XMP 元数据、数字签名(PKCS#7、PAdES B‑B/BT/BLT/BLTA)、时间戳
  • 专业特性:水印(文本/图片、位置/旋转、支持平铺、常量透明度与透明 PNG alpha 保留)、修订跟踪与汇总页、目录页、行号(页面/节/连续重启)、性能模式、转换进度回调、结构化文档标签(SDT)、文档复杂度分析

新增 DrawingML 矢量/渐变能力(近期)

  • 线性渐变:支持 tileRect、rotWithShape、scaled=false 等关键参数组合
  • 预设矢量形状扩展:diamond、parallelogram、trapezoid、chevron、rightTriangle、teardrop、octagon、star4/6/8/10/12、ribbon、wave、doubleWave,以及 leftArrow/rightArrow/upArrow/downArrow/leftRightArrow/upDownArrow 等箭头(含别名)

完成度评估

  • 测试通过:644 个单元测试全部通过(本地运行验证)
  • 建议按 3 个口径理解当前完成度:
    • 日常生产可用度:约 95% - 97%
    • README 宣称能力的兑现度:约 91% - 94%
    • 对 Word 像素级一致性/审计级标准的满足度:约 82% - 86%
能力域 评估 状态 说明
核心正文/段落/列表/表格/图片 94% - 97% 稳定 主转换链成熟,基础版式和常见文档结构覆盖充分;paragraph/tab/float/top-bottom/directional-wrap 已连续补强。
样式继承/主题色/字体选择 90% - 94% 稳定 样式继承、主题色、常见中英文字体路径较完整。
字段系统与延迟回填 94% - 97% 强项 PAGE/NUMPAGES、SECTION、REF/PAGEREF、IF、DOCVARIABLE、BARCODE、TOC 等覆盖深。
页眉页脚/脚注尾注/目录/行号 88% - 92% 稳定 多节继承、TOC 双遍回填、行号与分页字段已打通。
DrawingML/VML/图表 89% - 95% 可用但有降级 常见形状、图表类型和文本提取已实现;tight/through 多边形与 raster/vector mask 环绕、multi-contour wrapPolygon、wrapText side、字符/列/行级锚点主链已打通,复杂 /main shape 的降级栅格路径已从 placeholder 提升为真实 DrawingML 渲染,grouped/multi-image 复合形状现在不仅支持 picture-only live image layers,也支持多层 live vector background + live image layers + searchable text,并补上 picture rotation、srcRect crop、flip 与更深一层 nested group transform 语义;本地 file-backed、相对 source DOCX 目录的 external workbook target,以及 ms-excel:ofe|u|... 包装路径都已能直接抽取真实数据而不是退回 placeholder。
SmartArt/复杂图形 82% - 89% 部分降级 仍以栅格化主链为主,但优化布局覆盖更广;未知布局已从单一 generic fallback 继续推进到 relationship/balance/converging/diverging/target/alternating/stacked/timeline/funnel 等 layout-hint-driven placement,并补上更细的 connector、文本盒尺寸、shape routing 与 theme accent palette 语义,可提取文本在可解析时已尽量保留为 searchable text。
PDF/A/签名/校验/CLI 88% - 94% 稳定 PDF/A、签名、校验报告、CLI 诊断链路完整。
批注/修订/协作语义 70% - 80% 部分实现 汇总页和基础修订支持较好,但 Word 协作语义并非完全等价。
水印 88% - 92% 主链稳定 主转换链与后处理盖章链均支持文本/图片水印、位置、旋转、平铺、常量透明度和透明 PNG alpha 保留。

当前已验证的实现亮点:

  • 30+ 字段类型的嵌套解析与运行时页码/分节信息注入
  • 多节页面设置与页眉页脚继承、脚注/尾注内容输出
  • PDF/A 元数据与输出意图、合规性验证可选
  • 数字签名(包含可见签名外观,含 TSA 时间戳)
  • AltChunk 扁平化(HTML/MHTML/XML/WordprocessingML)
  • DrawingML/VML 文本与常见形状处理,混排图文的合理降级
  • ImageConverter 已补上隔离回归覆盖:页眉部件作用域 CreateScoped(...)、共享浮动锚点 marker 传递、以及混合 textbox+image anchored drawing 的双通道保留
  • StructuredDocumentTagHelper 已补上隔离回归覆盖:文本、日期、下拉/组合框、复选框,以及无显式类型时的 plain text fallback 与 display value 契约
  • RevisionHandler 已补上隔离回归覆盖:插入/删除识别、tracked-change 元数据提取、样式着色、修订收集/统计、显示文本,以及修订摘要页;同时修正为基于 OpenXML 实际的 InsertedRun / DeletedRun wrapper 解算修订信息
  • VmlHelper 已补上隔离回归覆盖:WordArt textpath 文本提取、VML shape / rect 基础形状映射,并修正 WordArt 样式中的文本色 color 会真正进入输出字体
  • FieldCodeHelper 已补上隔离回归覆盖:LISTNUM 编号格式、SHAPEDOG 开关解析、SYMBOL 十进制/十六进制/补充平面字符解码;Phase 0 里计划的关键 helper harness 已基本补齐
  • 浮动布局主链已覆盖:tab 对齐、same-page exclusion 持久化、TopAndBottom 统一路径、distT/distB/distL/distR、even-odd 多 contour wrapPolygon、基于区间中点 inside 判定的更稳健 polygon scanline、按 contour 顶点自适应切片的 polygon exclusion band、wrapText side、raster/vector Tight/Through 多段 mask 行扫描、避免过度合并 row-slice exclusion、同一行多 exclusion 时的最大可用间隙选择、跨页与代理画布共享的 marker 锚点上下文、浮动对象缓存最近一次已解析 marker 位置、竖排 character 水平锚点的 marker/cached-anchor 复用,以及正文竖排、页眉页脚竖排、自然分页 continuation paragraph anchored textbox(横排 + 竖排)、section 级竖排表格单元格、页眉页脚表格路径下的竖排 anchored textbox direction + marker binding、rightMargin / topMargin / bottomMargin 等 margin-edge offset/alignment anchors,以及跨页嵌套表格 textbox 的 marker-relative 回归;正文与页眉页脚中 BehindText / InFrontOfText 也已按 relativeHeight 更接近 Word 的分层排序
  • 复杂 /main DrawingML shape 在无法继续走向量/结构化路径时,现已优先使用真实 DrawingMLRenderer 栅格输出替代通用 placeholder PNG;generic wps:wsp 文本体和多图片组合在降级路径中的视觉保留显著更好
  • grouped/multi-image DrawingML 在经过 DOCX 落盘重开后,已可保留 picture-only live image layers;对多层 vector background + image layers 的混合对象,也能继续输出 live background + live images + searchable text,并补上 picture rotation、srcRect crop、flip 与 nested group transform 语义,而不再统一退化成复合 raster 背景;无文本的 grouped preset/custom geometry 也已能直接走 live vector path,而不是因为多 spPr 统一退回栅格
  • inline SmartArt 未知布局已从单一 process fallback 提升到基于 layout hint 的自适应 generic placement;relationship/balance/converging/diverging/target/alternating/stacked/timeline/funnel 等弱分类布局会继续套用更贴近模板意图的 connector、文本盒尺寸、shape routing 与 theme accent palette 策略,并在可解析时保留 searchable text

已知限制与规划

  • DrawingML 矢量化:常见几何子集已支持;复杂路径/公式、部分线端样式、复杂渐变仍回退栅格
  • 非图片 Tight/Through:矢量内容在无 wrapPolygon 时已可按 alpha mask 逐行避让并保留单行内多段 opaque run;显式 wrapPolygon 现已支持 even-odd 多 contour/孔洞场景,但极端自交路径仍未完全等价
  • wrapPolygon:当前已支持 even-odd 多 contour exclusion,并改为基于唯一交点分段后的中点 inside 判定与 contour 顶点自适应 band 切片;reopened/nested point container 也能继续还原 contour,但极端自交、多层嵌套和与 Word 专有几何规则完全一致的边界仍待继续补齐
  • character/line 相对定位:已接入 marker 驱动的字符/行级锚点解算,并补上跨页与代理画布的锚点上下文共享与最近一次解析结果缓存;段落跨页后再延迟落位的复杂组合仍有边缘差异
  • 极端嵌套锚点:文本框/表格/多栏中的多级浮动对象,在跨页与避让叠加场景仍有边缘差异
  • SmartArt:已优化多种布局的栅格化排版;未知布局现已采用 layout-hint-driven generic placement,并补上 relationship/balance/converging/diverging/target/alternating/stacked/timeline/funnel 等连接线、文本盒尺寸与 shape routing 策略,但仍未达到 Microsoft 各模板的完整 template-specific 语义
  • 图表数据源:支持嵌入式工作簿、缓存引用,以及本地 file-backed、相对 source DOCX 目录与 ms-excel:ofe|u|... 包装的外部工作簿路径;需远程/不可解析外部工作簿实时计算的场景将以占位呈现
  • 复杂 grouped/multi-image DrawingML shape 中,picture-only 与多层 vector background + image layers 的复合对象都已可输出 live 结构;picture 级旋转、srcRect 裁剪、flip 与 nested group transform 也已接入,但更深层层级、混合自定义几何与更复杂组合矩阵仍可能退回复合栅格背景,尚未达到 Word 级对象语义等价
  • AltChunk:复杂外部格式的深度展开有限,已保证常见 HTML/MIME 场景可用
  • 超大文档(1000+ 页):规划进一步性能优化(分块流式、粗排版预估等)

离 100% 还差多远(当前判断):

  • 核心正文主链大致还差 3% - 5%,剩余主要集中在极端浮动几何、多轮廓/孔洞 wrap、跨页与多级嵌套避让,而不是普通段落/列表/表格/图片。
  • README 宣称能力兑现度大致还差 6% - 9%,主要差在复杂 DrawingML/SmartArt、协作语义、以及部分审计级 PDF/版式一致性场景。
  • 如果目标是“和 Word 像素级一致”,仍有约 14% - 18% 的差距,主要不是功能缺失,而是复杂布局细节和降级路径的一致性问题。

改进计划(节选):

  • 修复并减少现有构建告警(空引用、未用变量、过时 API)
  • DrawingML 矢量路径与渐变继续覆盖更多预设与自定义子集,并把现有 live composite 从当前的 nested group/flip/多层 vector background 语义继续推进到更复杂的层级矩阵、混合几何与 Word 特有组合规则
  • SmartArt 未知/弱分类布局继续从当前的 layout-hint-driven generic placement + shape routing 推进到更多模板族的 connector path、node family 与文本盒尺寸策略
  • Tight/Through 真实轮廓避让继续补齐带孔洞/多轮廓/自交几何在跨页、多层嵌套和 Word 专有边界规则下的等价性,并继续压缩剩余边界差异
  • 图表文本布局使用新版 Skia API 提升标注清晰度
  • 将中文字体选择(当前默认 SimSun)外置为配置项并支持字体优先级
  • character/line 相对锚点继续推进到跨页、多级嵌套、文本框/表格组合场景下更接近 Word 的定位
  • AltChunk 的表格/列表再细化边界保留与空白折叠策略

快速开始

前置条件

  • .NET 10 SDK

构建

git clone <repository-url>
cd PowGrade.FileConverters.DocxToPdf/src
dotnet build

命令行

CLI 位于 src/PowGrade.FileConverters.DocxToPdf.Cli

cd PowGrade.FileConverters.DocxToPdf/src/PowGrade.FileConverters.DocxToPdf.Cli
dotnet run -- convert <input.docx> <output.pdf>
dotnet run -- <input.docx> <output.pdf>
dotnet run -- convert <input.docx> <output.pdf> --engine-report-json
dotnet run -- convert <input.docx> <output.pdf> --engine-root path/to/powgrade-pdf-runtime --engine-report-json
dotnet run -- convert <input.docx> <output.pdf> --engine-report-out engine-report.json --require-extracted-engine
dotnet run -- inspect-engine --json --require-extracted-engine

不带参数时会打印 usage 并以非 0 退出。

DOCX 预检/验证:

dotnet run -- preflight <input.docx|directory> --json
dotnet run -- preflight <input.docx|directory> --json --summary-only
dotnet run -- validate <input.docx|directory> --perfect --json
dotnet run -- convert <input.docx> <output.pdf> --summary-json
dotnet run -- convert <input.docx> <output.pdf> --summary-out report.json

preflightvalidate 只报告静态验证信号,不执行实际转换,因此不会采集 runtime degradation 或 placeholder 事件。 需要查看运行时降级时,使用 convert --summary-jsonconvert --summary-out,并读取 summary.runtimeDegradations。 当 preflight / validate 使用 --summary-only --json 时,输出会显式标记 runtimeDegradationsCaptured: false;而 convert --summary-json / --summary-out 会在 summary 中标记 runtimeDegradationsCaptured: true

校验已生成 PDF:

dotnet run -- validate <input.pdf> --pdfa PdfA2b
dotnet run -- validate <input.pdf> --signature
dotnet run -- validate <input.pdf> --pdfa PdfA2b --signature --json
dotnet run -- validate <input.pdf> --pdfa PdfA2b --json --out report.json

--json 输出机器可读报告;--out 同时写入报告文件。
--require-extracted-engine 可强制转换时使用已剥离的 PDF engine 边界。
--engine-root 或环境变量 POWGRADE_PDF_ENGINE_ROOT 可显式指定外置 PowGrade.Pdf.* runtime 目录。 inspect-engine 可在不执行转换时检查当前 runtime 的发现来源、命中目录与边界状态。

作为库使用

using PowGrade.FileConverters.DocxToPdf;
using PowGrade.FileConverters.DocxToPdf.Models;

using var input = File.OpenRead("input.docx");
using var output = File.Create("output.pdf");

var converter = new DocxToPdfConverter(new ConvertOptions());
converter.Convert(input, output);

var runtimeReport = converter.ConvertWithRuntimeReport("input.docx", "output.pdf");
Console.WriteLine($"Extracted boundary: {runtimeReport.EngineRuntimeBoundary?.IsExtractedBoundary}");

依赖注入:

services.AddDocxToPdf();
// 或(直接声明外置 engine runtime 目录)
services.AddDocxToPdf("/opt/powgrade-pdf-runtime");
// 或(带配置)
services.AddDocxToPdf(options =>
{
    options.EngineRootDirectory = "/opt/powgrade-pdf-runtime";
    options.RequireExtractedEngineBoundary = true;
});
// 或(从配置绑定)
services.AddDocxToPdf(configuration, "DocxToPdf");
// 或(同时接收 runtime 边界报告)
services.AddDocxToPdf(
    "/opt/powgrade-pdf-runtime",
    new Progress<EngineRuntimeBoundaryReport>(report =>
    {
        Console.WriteLine(report.IsExtractedBoundary);
    }));
// 或(从配置绑定并同时接收 runtime 边界报告)
services.AddDocxToPdf(configuration, new Progress<EngineRuntimeBoundaryReport>(report =>
{
    Console.WriteLine(report.EngineRootSource);
}));

var converter = app.Services.GetRequiredService<DocxToPdfConverter>();
// 或
var fileConverter = app.Services.GetRequiredService<IFileConverter>();
{
  "DocxToPdf": {
    "EngineRootDirectory": "/opt/powgrade-pdf-runtime",
    "RequireExtractedEngineBoundary": true,
    "AnalyzeDocumentBeforeConversion": true
  }
}

EngineRootDirectory 的解析优先级是:显式配置/参数 > 环境变量 POWGRADE_PDF_ENGINE_ROOT > 自动发现。
自动发现当前会优先检查运行目录本身,其次检查约定子目录(如 powgrade-pdf-runtimePowGrade.Pdf.Runtimeruntimes/powgrade-pdf),必要时也会检查源文档所在目录旁的约定 runtime 目录。
当需要确认最终命中了哪条路径时,优先运行 inspect-engine 或读取 engineRuntime.engineRootSource

高级配置示例

var options = new ConvertOptions
{
    // 进度与性能
    EnablePerformanceMonitoring = true, // 输出阶段耗时与计数器
    ProgressReporter = new Progress<ConvertProgress>(p =>
    {
        // p.Stage, p.CompletedItems/p.TotalItems, p.Message, p.CurrentItem
        // 例如:页级进度 "生成新页面"、"TOC Page N"
    }),

    // 图片下采样(大文档友好)
    DownscaleLargeImages = true,
    TargetImageDpi = 150,
    MaxImageMegapixels = 8.0,
    DownscaleJpegQuality = 85,

    // 中文字体优先级(按顺序尝试),未找到时回退到 DefaultFontName
    PreferredChineseFonts = new List<string>
    {
        "Microsoft YaHei", "SimSun", "NSimSun",
        "SimHei", "KaiTi", "FangSong",
        "PingFang SC", "Hiragino Sans GB", "WenQuanYi Micro Hei",
        "STSong-Light"
    },

    PageSize = Rectangle.A4,
    MarginLeft = 72f,
    MarginRight = 72f,
    MarginTop = 72f,
    MarginBottom = 72f,
    RenderHeadersFooters = true,
    GenerateTableOfContents = true,
    AddCommentsSummaryPage = true,
    Watermark = new WatermarkOptions
    {
        Text = "CONFIDENTIAL",
        FontSize = 48f,
        Opacity = 0.3f,
        Rotation = -45f,
        Tiled = true
    },
    Encryption = new PdfEncryptionOptions
    {
        UserPassword = "user123",
        OwnerPassword = "owner123",
        AllowPrint = true,
        AllowCopyContent = false
    },
    PdfACompliance = PdfAComplianceLevel.PdfA2b,
    SignatureOptions = new SignatureOptions
    {
        CertificatePath = "certificate.pfx",
        CertificatePassword = "password",
        SignatureType = SignatureType.PadesBT,
        Reason = "Document Approval",
        Location = "Office"
    }
};

var converter = new DocxToPdfConverter(options);
converter.Convert("input.docx", "output.pdf");

项目结构

src/
├── PowGrade.FileConverters.DocxToPdf/
│   ├── DocxToPdfConverter.cs
│   ├── ServiceCollectionExtensions.cs
│   ├── Converters/
│   ├── Rendering/
│   ├── Rasterization/
│   ├── Helpers/
│   ├── PdfEngine/
│   └── Models/
├── PowGrade.FileConverters.DocxToPdf.Cli/
└── PowGrade.FileConverters.DocxToPdf.Tests/

tests/
├── fidelity-corpus/
└── fixtures/

tools/
└── DocxFixtureGenerator/

测试

cd src/PowGrade.FileConverters.DocxToPdf.Tests
dotnet test

已跟踪的基线夹具位于 tests/fidelity-corpus/tests/fixtures/paragraph-converter/

tests/fidelity-corpus/*.json sidecar 现可为样本声明页数、允许的 perfect-conversion warning 片段,以及 page-level PDF content assertions(containsText / doesNotContainText / matchesPattern / doesNotMatchPattern / containsTextsInOrder)和文本级 scorecard(pdfTextCountAssertions / pdfTextPageAssertions),便于把 placeholder/raster fallback、关键文本存在性、基础阅读顺序和跨页分布逐步纳入 scorecard。

tests/fidelity-corpus/*.pdf 是仓库内的回归参考 PDF,不是 Microsoft Word 打开 DOCX 时的权威视觉真值。当需要按 Word 实际打开态逐页比对时,先用下面的脚本导出 Word 页面截图,再让 .codex-out/sample1/compare-viewer.html 右侧优先加载这些截图:

powershell -ExecutionPolicy Bypass -File .\tools\ExportWordPageScreenshots.ps1 `
    -DocxPath .\tests\fidelity-corpus\sample1.docx `
    -OutputDirectory .\.codex-out\sample1\word-baseline

导出脚本会通过 Word 对象模型把每页导出为 Enhanced Metafile 再栅格化成 PNG,不依赖屏幕截图;生成完毕后,compare viewer 会优先使用 .codex-out/sample1/word-baseline/page-{n}.png,仅在截图缺失时回退到 tests/fidelity-corpus/sample1.pdf

当需要重新生成这些样本时,运行:

dotnet run --project tools/DocxFixtureGenerator/DocxFixtureGenerator.csproj

覆盖范围:段落/表格/列表/图片、样式继承、字段解析、DrawingML/SmartArt、图表、OMML、页眉页脚、页面边框、PDF 输出校验、CLI 命令等。

许可证

MIT License(见根目录 LICENSE)。

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on PowGrade.FileConverters.DocxToPdf:

Package Downloads
PowGrade.FileConverters.DocxToPdf.Cli

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0 170 4/30/2026