同样是 50 页,为什么这个 PDF 大了十倍:一套可复用的压缩前检查
那天离提交只剩十分钟,内容已经校对三遍,上传页面却只回了一句:“文件超过限制。”真正耽误人的,往往不是压缩命令,而是我们根本不知道 PDF 为什么会这么大。
先别压缩,PDF 不是一种单一文件
文字、图片和字体住在同一个容器里
PDF 更像一个打包好的页面描述容器。它可以保存字符、字体子集、矢量图形、透明对象、照片、扫描页、表单和元数据。两个看起来同样是 50 页的文件,内部构成可能完全不同。
一份由 Markdown 或 Word 直接导出的技术文档,正文通常以字符对象为主,图片数量有限。另一份 50 页扫描件,可能每页都嵌入一张接近 A4 尺寸的高分辨率彩色图。页面数相同,不代表可压缩空间相同,更不代表应该使用同一种策略。
工程上最容易犯的错误,是把“PDF 太大”直接翻译成“把画质调低”。如果体积主要来自未裁剪的扫描图,这样做可能有效;如果主要来自重复嵌入的字体、附件或已经压缩过的 JPEG,再次降低画质未必能换来明显收益。
第一步先建立一个基线
先记录页数、文件大小、PDF 版本与页面尺寸。Poppler 提供的 pdfinfo 足够完成第一轮检查。
pdfinfo document.pdf
输出中的 Pages、Page size、File size 和 PDF version 值得保留。它们不是结论,却是后续对比的基线。压缩之后只看“文件能打开”远远不够,还要确认页数没有变化、页面尺寸没有意外改变,并记录体积到底减少了多少。
为了避免覆盖原件,后续所有操作都应输出到新文件。这个习惯很朴素,却比任何参数都重要。PDF 重建可能影响链接、表单、书签或文本层,原件必须留在手里。
字体和可提取文本是第二个线索
接下来检查字体与文本层。
pdffonts document.pdf
pdftotext document.pdf - | tr -d '[:space:]' | wc -m
如果 pdffonts 能列出多种字体,pdftotext 也能提取大量字符,文件大概率包含可用文本层。如果字体列表为空、提取字符接近零,而页面肉眼看上去又有大量文字,文件更可能是扫描图组成的。
这仍然不是绝对判断。有些文档把文字转成矢量轮廓,画面清楚却无法提取字符;有些扫描件叠加了 OCR 文本层,因此既有整页图片,也能复制文字。压缩前检查的意义不是给文件贴一个永久标签,而是收集足够多的信号。
找到真正占空间的对象
用 pdfimages 看整页大图
pdfimages 可以列出页面中的图像对象、尺寸、颜色空间、编码方式和分辨率。
pdfimages -list document.pdf
如果每一页都有一张宽高接近页面比例的大图,且分辨率达到数千像素,体积通常主要花在扫描图上。此时调整图像分辨率、色彩空间和 JPEG 质量,往往比清理 PDF 结构更有效。
如果图像很少,文件却异常大,就要继续检查是否嵌入了附件、重复字体或其他对象。qpdf 可以先验证文件结构是否基本正常。
qpdf --check document.pdf
结构警告不一定代表文件损坏,但它提醒我们:不要在没有验证的情况下直接批量覆盖输出。能被阅读器打开,只说明阅读器足够宽容,并不说明文件内部完全健康。
抽样页比只看第一页可靠
混合型 PDF 很容易让脚本误判。封面可能是文字,正文可能是扫描图;正文能复制,附件却全部来自扫描仪。只检测第一页,会把局部特征当成整份文档的结构。
可以从封面、普通正文、图表密集页和附件中抽样提取文本。
for page in 1 5 10 20; do
printf '\n--- page %s ---\n' "$page"
pdftotext -f "$page" -l "$page" document.pdf - | sed -n '1,6p'
done
页码需要根据实际页数调整。真正值得自动化的,不是某个固定压缩参数,而是这套抽样逻辑。它能帮助脚本决定采用结构优化、图像降采样,还是保留原文件并提示人工检查。
不同来源需要不同策略
文字型文档通常应优先保留字符对象、字体和矢量线条。对它进行整页栅格化,可能让正文失去搜索与复制能力,还会让小字号变模糊。
扫描型 PDF 的主要负担通常是页面图像。此时适度降低图像分辨率、把不必要的彩色页转为灰度,可能带来明显效果。不过工程图、浅色批注和带颜色含义的表格不能一概转灰。
图片与文字混合的演示稿最麻烦。照片适合有损压缩,图标与截图则容易在低质量 JPEG 下出现色块和文字毛边。可靠的策略应允许不同对象走不同路径,而不是把整份文件统一磨平。
把压缩做成可验证的流程
Ghostscript 预设只是起点
本地批处理常会使用 Ghostscript。下面是一条常见的起始命令,而不是适用于所有文件的标准答案。
gs -sDEVICE=pdfwrite \
-dCompatibilityLevel=1.6 \
-dPDFSETTINGS=/ebook \
-dNOPAUSE -dQUIET -dBATCH \
-sOutputFile=output.pdf \
document.pdf
/ebook 在体积和阅读质量之间做了一组预设取舍。它适合快速建立候选输出,但生产流程不应只因为命令返回 0 就宣布成功。某些已经优化过的文件可能缩小很少,甚至因为重新编码而变大。
输出文件至少做三类回归检查
第一类是结构检查:页数、页面尺寸和基本打开能力。第二类是内容检查:随机抽取文本,确认字符数量没有异常下降。第三类是视觉检查:渲染几张高风险页面,查看细字、表格、二维码、浅色标注与图片边缘。
可以用下面的方式快速对比关键指标。
pdfinfo document.pdf | findstr /C:"Pages" /C:"File size"
pdfinfo output.pdf | findstr /C:"Pages" /C:"File size"
pdftotext document.pdf original.txt
pdftotext output.pdf compressed.txt
在 Linux 或 macOS 上可将 findstr 换成 grep -E 'Pages|File size'。文本差异并不自动等于错误,但如果压缩后提取结果突然为空,就需要确认流程是否把页面整体转成了图片。
临时任务和工程管线不是同一个问题
如果只是偶尔遇到一次上传限制,搭建完整命令行环境反而会增加成本。这时使用 PDFCompress 这样的在线入口,选择合适的压缩强度并检查结果,通常比临时安装工具链更直接。
如果每天都要处理同一来源的数百份文件,就应该把检测、压缩、验证和失败回退写入流水线。工具选择取决于任务频率与风险,而不是“命令行一定更专业”或“网页一定更省事”这种简单判断。
结语
好的压缩从识别文件开始
PDF 压缩不是把一个滑块拖到最低。先看页数和尺寸,再检查文本、字体和图像,最后根据文件类型选择策略,才能知道体积减少是来自合理优化,还是来自信息被悄悄丢弃。
下一次提交页面提示文件过大时,先别急着重导出十遍。花一分钟做预检,往往能省下后面二十分钟的试错。真正可复用的能力,也不是记住某条神奇命令,而是让每个输出都有依据、能比较、可回退。
本作品采用《CC 协议》,转载必须注明作者和本文链接
关于 LearnKu
推荐文章: