夜雨聆风学习资料网

ARTICLE · 1113823

OFD⇄PDF 选型决策树:别按榜单选,按这 5 个问题选

OFD⇄PDF 选型决策树:别按榜单选,按这 5 个问题选

前两篇的结论可以浓缩成一句话:

榜单告诉你"在 6~7 个特定文件上谁快",不告诉你"在你的业务里谁对"。

这一篇是可直接拿去用的选型手册。


一、先做筛选:4 个问题砍掉一半选项

在看任何性能数字之前,先回答这四个问题。它们不是偏好问题,是能不能用的问题。

Q1  转换后的文件要能被搜索/复制/抽取吗?Q2  你的文档有签章/发票/复杂图形吗?Q3  体积有上限吗(上传限制、存储成本)?Q4  能进商用项目吗(许可证)?

Q1 决定技术路线(一票否决)

这是最重要的一问,因为它直接决定你落在 01 篇那张四路线图的哪一层:

要可搜索/可复制   │   ├─ 是 → 只能走「路线 A:矢量重绘」   │        候选(实测中表现最好者)   │        OFD→PDF:  go-zc310 / go-ofdgo / rust-easyofd   │                   java-ofdrw / node-ofd2pdf   │        PDF→OFD:  go-zc310 / go-ofdgo / node-jsofd   │   └─ 否 → 路线 B/C/D 全都可用,按速度选            路线 B 轮廓化   java-ofdrw     体积涨 10~26 倍            路线 C 栅格化   python-pdf2ofd 最简单,0 文本            路线 D 抽取式   rust-easyofd   ⚠️ 实测输出不可用

⚠️ 路线 D(rust-easyofd 0.1.4 的 PDF→OFD)实测是不可用的:输出空页 / CID 乱码 / 版面固定 (10,20)。不要因为它"最快"就选它。

⚠️ 但这是版本 0.1.4 的状态。输出空页、CID 乱码属于"实现缺失",不是路线固有限制(对比:路线 B/C 丢文本才是固有的)—— 作者修掉它们只是时间问题。用之前先测当前版本。

Q2 决定验收样本

你的文档越复杂,越不能用 hello 验收:

你的文档特征
必须用它对应的样本验
签章、公章
zsbk
发票
ano
(注意 Stamp 注解)
PPT/Word 导出的复杂版面
intro
(照妖镜)
数百页以上
1000-pages
字体全内嵌 + 图表多
GBT_33190-2016
官方文档、公文
GBT_33190-2016

Q3 决定能否用轮廓/栅格路线

实测体积比(输出 / 源):

go-zc310       0.43 ~ 1.43   ✅ 全部 ≤1.5xgo-ofdgo       0.52 ~ 2.59java-ofdrw     1.00 ~ 26.48  ⚠️python-pdf2ofd 1.04 ~ 20.63  ⚠️node-jsofd     2.08 ~ 29.25  ⚠️

有体积上限的场景,java-ofdrw / pdf2ofd / jsOFD 基本可以划掉。

Q4 是硬门槛

ofd-libraries.md 收录 66 个库,其中 19 个标注「无」许可证。

实测参测的 8 个 OFD→PDF + 6 个 PDF→OFD 共 14 个转换器实例里(去重后 10 个底层库):

⚠️ jsyzdej/ofd2pdf  →  无许可证  →  商用直接排除其余 13 个           →  Apache-2.0 / MIT  →  可用(仍需法务确认)

⚠️ 未声明许可证 ≠ 免费可用。ofd-libraries.md 中"无"只表示该库未声明许可证;按通行做法,未声明即默认保留所有权利。这条比任何性能数据都优先。


二、OFD→PDF 决策树

                        你的 OFD → PDF 需求                                │        ┌───────────────────────┼───────────────────────┐        ▼                       ▼                       ▼   要文本可搜              复杂图形/版面            只要快/要小        │                       │                       │        ▼                       ▼                       ▼  go-zc310                go-ofdgo               rust-easyofd  文本相似度 4 胜          intro 99.62% 最高       速度 5 胜  ano=7280 字符            hello/999 像素高        1000-pages 614KB  体积比接近数科                                  ⚠️ 必须自验 intro 类样本        │                       │                       │        └───────────┬───────────┴───────────┬───────────┘                    ▼                       ▼              Java 栈 → java-ofdrw      Node → node-ofd2pdf              小文件接近数科            字符数 2 胜、intro 1.1MB              1000-pages 文本相似度最高              ⚠️ 体积大、速度慢

一句话决策:

条件
选
有且仅有"要文本可搜"
go-zc310
有且仅有"复杂版面要像"
go-ofdgo
有且仅有"要快"
rust-easyofd(前提:自验复杂样本)
三个都要
go-zc310
,速度不够再叠加 rust

三、PDF→OFD 决策树

                        你的 PDF → OFD 需求                                │        ┌───────────────────────┼───────────────────────┐        ▼                       ▼                       ▼   要文本可搜              要像素级像              简单文档/演示        │                       │                       │        ▼                       ▼                       ▼  go-zc310                java-ofdrw            python-pdf2ofd  唯一「可用+有序          hello 99.98%           最简单  +可提取」三者兼得        1000-pages 99.62%      999 像素最高  体积比 0.43~1.43       ⚠️ 0 文本              ⚠️ 0 文本  ano 99.75%(读注解)    ⚠️ 10~26 倍体积       ⚠️ 1000 页 34.2s        │                       │                       │        └───────┬───────────────┴───────────┬───────────┘                ▼                           ▼      复杂图形 → go-ofdgo            Node 环境 → node-jsofd      intro 99.80% 全场最高          提取量第二      提取量最大                     ⚠️ 体积最大、相似度低

一句话决策:

条件
选
默认答案go-zc310
复杂图形为主、不搜字
go-ofdgo / java-ofdrw
纯展示演示、接受 0 文本
python-pdf2ofd
Node 环境、必须能搜字
node-jsofd(注意相似度低)
任何场景
排除 rust-easyofd 0.1.4
(先测新版,可能已修)

四、选型矩阵(速查表)

OFD → PDF

转换器
成功率
文本
复杂版面
体积
速度
许可
go-zc310
100%
★★★★★
★★★★
★★★★★
★★★
Apache-2.0
go-ofdgo
100%
☆☆☆☆☆
★★★★★
☆☆☆☆☆
★★☆
Apache-2.0
rust-easyofd
100%
★★★★
☆☆☆☆☆
★★★★★
★★★★★
Apache-2.0
java-ofdrw
100%
★★★★
★★★★
★★★
★★☆
Apache-2.0
node-ofd2pdf
100%
★★★★
★★★
★★★★
★★★
Apache-2.0
python-easyofd
67%
★★☆
☆☆☆☆☆
★★★
★★☆
Apache-2.0
python-ofd2pdf
67%
☆☆☆☆☆
★★★
★★☆
★☆☆
⚠️ 无

星级为依据实测数据的相对归纳,非官方评分。☆ 表示该项实测明显短板。

两处需注意:python-ofd2pdf 的"复杂版面"给 ★★★ —— 它在像素表里 hello 99.95%、1000-pages 99.32% 各拿 1 胜(共 2 胜),但源文档同时标注其矢量图形不支持、无法提取文本,所以只给 3 星。

速度一栏与"胜出次数"不完全对齐(如 go-zc310 0 胜仍给 3 星),因为星级综合了多页场景表现(intro、1000-pages)而非单列第一。

PDF → OFD

转换器
文本
像素
体积
速度
读注解
许可
go-zc310
★★★★★
★★★★
★★★★★
★★★
✅
Apache-2.0
go-ofdgo
★★★★
★★★★★
★★☆
★★☆
✅
Apache-2.0
java-ofdrw
☆☆☆☆☆
★★★★★
☆☆☆☆☆
★★☆
未记录
Apache-2.0
python-pdf2ofd
☆☆☆☆☆
★★★
☆☆☆☆☆
★☆☆
未记录
MIT
node-jsofd
★★★
★★★★
☆☆☆☆☆
★★☆
❌
MIT
rust-easyofd
☆☆☆☆☆
☆☆☆☆☆
(空页)
★★★★★
未记录
Apache-2.0

"读注解"一列的证据强度不同,请勿当作实测结论:

  • ✅ go-zc310、go-ofdgo —— 源文档明确列出能力含"注解"
  • ❌ node-jsofd —— 源文档明确"不转换注解/渐变/图案/Type3/剪裁"
  • 未记录java-ofdrw
    、python-pdf2ofd、rust-easyofd —— 源文档只描述其技术路线(轮廓化 / 栅格化 / 抽取),未说明是否处理注解。go-zc310 在 ano 上 99.75% 的高像素分只能间接说明源 PDF 里的 Stamp 被覆盖了,不能证明是"读注解"做到的。

若你的文档大量依赖 PDF 注解(发票骑缝章等),这一列请自行验证。


五、组合拳:真实项目往往需要两套

单一库几乎总有短板。实测数据支持三种组合策略。

策略 A:文本优先(档案、公文、发票)

  go-zc310  作为默认转换器      +  人工复核 / 像素门禁(阈值可设 98%)      +  文本提取校验(字符数 > 0 且非乱码)

关键:加一道"文本非乱码"检查。 这是 rust-easyofd 那类"有字符但是 CID 乱码"故障唯一的拦截点。

策略 B:分级路由(复杂业务)

  简单文档(纯文本、少图、无签章)  →  go-zc310(快、体积小)  复杂文档(多层图形、背景图)      →  go-ofdgo(intro 99.62%)  签章/发票                        →  go-zc310(读 Stamp 注解)

判定条件可用转换前的特征:文件大小、页数、是否含 Annots、是否含 Image 资源数量。

策略 C:双轨并行(高可靠归档)

  轨道 1  go-zc310      → 保文本,供检索/抽取  轨道 2  java-ofdrw    → 保外观,供忠实呈现/打印  两份都存,元数据记录来源轨道

代价是存储翻倍(1000-pages 实测 3.1M vs 57.4M,差 18 倍)。先算清存储成本再上。

反模式(别这么干)

✗ 按"综合第一"选 —— 没有综合第一,各维度冠军是不同库✗ 只跑 hello 就验收 —— 67% 成功率的库 hello 也可能过✗ 用像素相似度验收可搜索性 —— 两者无关(go-ofdgo 99.62% / 文本 0)✗ 因为"快"就选 rust-easyofd 0.1.4 做 PDF→OFD —— 输出空页(但先测新版再排除)✗ 转换后就归档 —— 归档另需固定性验证与制度检查✗ 把转换后的签章外观当签名有效性 —— 信任链不随格式转换

六、语言栈与许可的交叉筛选

技术之外,选型还要过两道非技术关。

6.1 语言栈决定你能部署什么

你的栈
可选范围
Go 服务
go-zc310、go-ofdgo(首选,Apache-2.0)
Rust 服务
rust-easyofd(OFD→PDF 可用;PDF→OFD 在 0.1.4 不可用,需测新版)
Java / 政企
java-ofdrw(唯一成熟 Java 方案)
Node / 浏览器
node-ofd2pdf(OFD→PDF)、node-jsofd(PDF→OFD)
Python 脚本
python-easyofd(OFD→PDF,可接受 67%)、python-pdf2ofd(演示用)
C++ / .NET
有库但未进入本次实测,需自行验证

6.2 许可证

实测共 14 个转换器实例(OFD→PDF 8 个 + PDF→OFD 6 个),去重后对应 10 个底层库:

Apache-2.0   10 个实例 / 6 个库             go-zc310、go-ofdgo、rust-easyofd、java-ofdrw、             python-easyofd、@miconvert/ofd-to-pdfMIT           3 个实例 / 3 个库             python-ofdreader、wanglrebe/pdf2ofd、Hufe921/jsOFD无            1 个实例 / 1 个库  ⚠️ jsyzdej/ofd2pdf

⚠️ ofd-libraries.md 中"无"只表示该库未声明许可证。按通行做法,未声明即默认保留所有权利,不等于免费可用 —— 商用前必须法务确认或联系作者。(此为法律常识补充,非基准测试文档原文结论。)


七、上线前的六项自检

⚠️ 选型前先确认版本。本系列数据绑定特定版本(见  第 〇 节),go-ofdgo 曾在一次提交里修掉三个 PDF→OFD bug —— 榜单排名可能在你读这篇文章时就变了。第 0 项是版本,不是能力。

不管选谁,上线前跑完这六项:

□ 0. 已锁定库版本号,并记录在选型文档里□ 1. 用自己的真实文档跑通(不是 hello)□ 2. 复杂样本(intro 类 / 签章 / 发票)全部通过□ 3. 文本提取 > 0,且人工确认不是乱码□ 4. 像素门禁达标(建议 ≥98%,按业务调)□ 5. 体积在预算内(算 26 倍膨胀场景能否接受)□ 6. 许可证已法务确认

再加两条面向生产的:

□ 7. 大页数(1000+)压测,实测单页耗时可接受□ 8. 失败有兜底:转换失败不能丢件,要进重试或人工队列

八、一句话收束

选型的正确顺序:  1. 先问「要文本吗」      → 定路线,砍掉一半选项  2. 再问「能商用吗」      → 砍掉无许可证的  3. 再问「文档有多复杂」  → 定验收样本  4. 最后才看「谁最快」    → 在剩下的里选顺序反了,就会在"7 胜 0 负"上翻车。

参考资料

  • ofd-benchmark/docs/ofd-to-pdf.md
    、docs/pdf-to-ofd.md(全部数据)
  • ofd-benchmark/docs/ofd-libraries.md
    (66 个库能力/许可证)

相关学习资料