qpdf 12.4.2 是命令行的 PDF 处理工具,Windows 只有安装器 12070517 字节,解开之后主程序 qpdf.exe 只有 45814 字节,剩下 47 MB 全是随附的 DLL。

它要解决的是:给一份 PDF 加密码、把一份长文档按页拆开、或者把几个文件按指定顺序拼起来,这些事图形工具要么收费要么只能做一半。

这次拿同一批文件对比了三件事:合并 95 页、加 256 位密码、按页拆分,顺带和另一个命令行工具比了速度。

主程序只有 45814 字节

这个小体积是它最大的特点:逻辑全在 exe 里,重活交给旁边的库。

项值说明
安装器12070517 字节NSIS 打包,可用 7-Zip 直接拆
解压后47374236 字节约 45 MB,大头是依赖库
qpdf.exe45814 字节主程序本体
附带工具2 个fix-qdf 302869 字节、zlib-flate 57296 字节

拆安装器比装一遍快

NSIS 包用 7-Zip 直接解压就能得到可用的目录,不写注册表、不建快捷方式。想要便携版不必找绿色包,自己拆一次就行。

fix-qdf 和 zlib-flate 是给调试用的

一个修 QDF 格式(PDF 的纯文本形式),一个压解 zlib 流。日常处理用不到,改 PDF 结构出问题时才用得上。

三件事都不到 65 毫秒

同一批文件,合并、加密、拆分三种操作的耗时都在几十毫秒。

操作耗时结果
合并三个文件38 ms95 页,11515 字节
加 256 位密码46 ms12166 字节
按页拆开61 ms95 个单页文件

比另一个工具快五倍多

同样合并 95 页,另一个 Go 写的命令行工具用了 207 毫秒,qpdf 用 38 毫秒。差别不在算法,在启动:45814 字节的 exe 加载几乎不花时间。

拆分耗时随页数线性涨

61 毫秒拆出 95 个文件,平均每页 0.64 毫秒。要拆几百页的文档,这个数字会等比放大。

加密出来是 AESv3

加完密码用 --show-encryption 回读,能看到具体用的算法和权限位。

字段值
R(加密修订版)6
P(权限位)-4
stream / string / file encryption methodAESv3 / AESv3 / AESv3
User passworduser
权限项提取、打印、修改全部 allowed
qpdf 12.4.2 在 Windows 控制台里的输出:先是 version 12.4.2 与版权提示,加密 256 位后回读显示 R=6、P=-4、User password 为 user,stream、string、file 三种加密方式都是 AESv3,权限项全部 allowed,最后一行 show-npages 返回 95

三层都是 AESv3

文档流、字符串、文件本身用的都是 AESv3,对应 256 位。回读时命令行会要求提供密码,否则只回一行口令错误。

P 值是负数说明权限设得很宽

P 为 -4 表示除了少数几项,提取、打印高低分辨率、修改、批注全部允许。要限制打印或复制,得在建加密时显式调整权限参数。

不规范的 PDF 会给警告但不失败

这次用来测试的三个文件是按最简结构手写的,合并时 qpdf 报了两行警告。

警告含义
file is damaged文件结构有缺失
can't find startxref缺少交叉引用表指针

退出码 3,但产物写出来了

11515 字节的合并结果正常生成,后续加密和拆分都基于它跑通了。所以退出码 3 表示"有结构问题但处理完了",不是失败。

脚本里要区分警告与失败

它是按警告严重程度给退出码的:0 干净、3 有警告、2 才是真错误。批处理里判断 0 或 3 都当成功更稳妥。

什么场景值得上

要把 PDF 处理写进脚本、又希望启动开销接近零的时候。

场景合适度说明
批量加密码高46 毫秒一份,可循环
按页拆分长文档高95 页 61 毫秒
合并与重排页序高--pages 支持指定页区间
看 PDF 内容、做批注低它不渲染页面

它和带界面的 PDF 工具分工不同

图形工具能看见页面,适合手工挑页;qpdf 看不见,适合把规则写成参数跑一批。要按视觉顺序挑页,先用界面选好,再用 qpdf 落地。

授权与费用

Apache-2.0 许可,个人与商业环境都不收费。源码在 GitHub 上,主要语言 C++,Windows 只有 NSIS 安装器,其他平台提供压缩包。