平时我处理PDF文件的场景挺多的,从合并几十份合同到给扫描件加页码,再到把客户发来的图片型PDF转成可编辑Word,几乎每周都要折腾几次。以前图省事,直接搜在线工具,但用久了就发现两条路都不太好走:在线网站免费额度少、上传速度慢、还有文件泄露的顾虑;商业软件价格不低,破解版又实在不敢用。直到朋友推荐了这个完全开源免费的PDF处理工具——Stirling PDF,实测了一段时间,感觉它是目前把“开源免费、功能全面、部署简单”三者平衡得最好的方案,支持PDF编辑转换、拆分合并、添加水印、OCR识别、加密解密等几十项功能,个人和公司内网部署都很合适。这篇文章就把我从下载到部署、从配置到实际使用中踩过的坑和验证过的操作,全部分享出来。
1. 为什么我最终放弃了在线工具和商业软件
1.1 在线PDF网站的坑,很多人可能还没意识到
在线PDF工具最大的问题是文件安全,虽然大多数小众站点没有恶意,但你根本不知道文件上传到了哪台服务器、会被存储多久、会不会被用于其他用途。有一次我要处理一份带有客户手机号和身份证扫描件的材料,本来想用免费在线工具压缩一下,同事直接提醒我,这种信息一旦传出去,泄露责任说不清楚。从那次之后,凡是涉及隐私数据的文件,我坚决不上传任何在线服务。
除了安全,在线工具的免费限制也很让人头疼。相信用过的人都懂,免费用户往往会遇到文件大小限制、页数限制、每天转换次数限制,最关键的是输出文件会带水印或需要等待很长的队列时间。即使你只是简单地把两页PDF合并成一个新文件,某些网站也要求注册才能下载,这种体验非常差。
商业软件方面,Adobe Acrobat Pro虽然功能强大,但订阅价格对个人用户不友好,公司批量采购又是一笔预算。开源方案最直接的好处是:软件本体免费,部署在自己可控的服务器或本地电脑上,文件数据不出内网,彻底解决隐私和成本这两座大山。
1.2 免费开源不代表随便拿,选型要看这几项硬指标
很多人一听到“开源”就认为等于“随便用”,这是误解。开源项目的许可证决定了你能怎么用它。如果是个人试用,几乎什么许可证都无所谓;但如果要在公司内部署,甚至基于它做二次开发集成到自己的系统里,许可证就是红线。
Stirling PDF 用的是 Apache License 2.0,这个许可对公司商用场景非常友好:你可以自由使用、修改、分发,甚至把它集成进商业系统,不需要开源你自己新增的代码。相比之下,如果某个工具用的是 GPL 协议,而你又想把它嵌入到闭源商业产品里,就会有比较严格的传染性限制,容易埋下合规风险。
选择开源项目时,我还习惯看三个指标:GitHub 上的 Star 数量和更新频率、Issue 区是否有人维护跟进、Docker 镜像是否长期持续发布。选型时切忌只看 Star 数,很多项目 Star 很高但作者弃坑已久,安全漏洞没人修,反而比商业软件更危险。Stirling PDF 在这方面表现不错,社区活跃、更新频率高,这也是我决定深入使用它而不是选择其他开源 PDF 项目的原因。
1.3 同类开源PDF工具横向对比
给同样喜欢自部署的朋友做一个简单对比,便于选型:
| 工具 | 核心定位 | 许可证 | 部署难度 | 适合场景 |
|---|---|---|---|---|
| Stirling PDF | 全功能PDF处理工具箱(转换、合并、OCR、水印) | Apache 2.0 | 低(Docker秒级启动) | 个人/公司内网,需要一站式解决方案 |
| PDFsam Basic | 专注PDF拆分、合并、旋转、提取 | AGPL | 中(桌面应用为主) | 只需要拆分合并的轻量需求 |
| OCRmyPDF | 纯OCR识别并生成可搜索PDF | Apache 2.0 | 中(命令行工具) | 需要批量处理扫描件等高级用户 |
| pdfarranger | 可视化页面级编辑 | GPL | 低(桌面应用) | 手动调整PDF页面顺序 |
Stirling PDF 的优势在于提供Web操作界面,所有人用浏览器就能访问,不需要在每台电脑上安装客户端。对于公司内部员工来说,打开浏览器即用,体验门槛最低。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Stirling PDF的核心能力拆解与部署准备
2.1 它能做什么,不仅仅是你想象中的“PDF编辑”
初看你可能以为这就是个“合并PDF、拆分PDF”的小工具,实际部署完打开界面后,你会被它的功能列表惊到。Stirling PDF 把功能分成了几个大板块:转换、安全与权限、页面操作、文本与图形、OCR识别、压缩优化等,总计二三十项常用操作。它内部并没有从零再造一套PDF解析引擎,而是集成了多个成熟开源组件。
具体来说,PDF页面拆分合并依赖的是 Apache PDFBox,这是Java生态里非常成熟的PDF处理库;文件格式转换则依赖 LibreOffice 做底层转换;OCR识别调用的是 Tesseract OCR 引擎,配合你额外下载的不同语言训练数据包实现中文、英文等文字的识别;PDF压缩用到的是 Ghostscript 和 qpdf 等开源命令行工具。整个项目等于把一个复杂的“工具箱”包了一层美观的Web界面,并把它们无缝串联起来。所以它处理绝大多数个人和办公场景的需求,性能是完全足够的。
2.2 Docker部署是最推荐的方式,三个步骤启动服务
Stirling PDF支持很多种部署方式,可以由源码构建、用jar 包直接运行,也可以用Docker容器方式部署。我最推荐Docker方式,一是依赖隔离,Java、LibreOffice、Python 等运行环境镜像里已装好,不会和你本机环境冲突;二是升级方便,后续版本发布后拉取新镜像重启容器就能完成升级。
我是在一台Ubuntu 22.04服务器上部署的,配置要求不高,2核CPU加2GB内存就能稳定跑日常任务。如果只是本地个人电脑想体验一下,用Windows的Docker Desktop也能一样操作。
先确认机器上已安装 Docker 和 Docker Compose 插件。快速验证命令:
bash复制docker --version
docker compose version
如果还没有安装,可以参考 Docker 官方文档,这里不再赘述。安装完成后,找一个目录作为工作目录,创建 docker-compose.yml:
yaml复制version: "3.3"
services:
stirling-pdf:
image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest
container_name: stirling-pdf
ports:
- "8080:8080"
volumes:
- ./trainingData:/usr/share/tessdata
- ./extraConfigs:/configs
- ./customFiles:/customFiles
environment:
- DOCKER_ENABLE_SECURITY=false
- LANGS=en_GB,en_US,de_DE,fr_FR,ar_AR,zh_CN
restart: unless-stopped
简单解释一下几个关键参数。
ports左侧8080是宿主机访问端口,右侧8080是容器内服务监听端口。如果你宿主机 8080 已被占用,改成8081:8080即可。./trainingData:/usr/share/tessdata是OCR中文识别必须的目录映射。后面会细说。LANGS环境变量决定界面语言下拉框里能选哪些语言,我把中文zh_CN加进去了。
启动命令:
bash复制docker compose up -d
首次启动会拉取镜像,镜像比较大,几百MB到1GB左右,取决于版本,耐心等待。启动成功后浏览器访问:
bash复制http://你的服务器IP:8080
看到Web界面就说明服务已正常运行。
2.3 不用Docker的本地启动方式,给不喜欢容器的人
如果你不想引入Docker,也可以用可执行jar包方式运行。先去官方GitHub Releases页下载最新的 .jar 文件,然后确保本机已经安装了 JDK 17 或更高版本,执行:
bash复制java -jar Stirling-PDF.jar
这种方式更接近传统软件的使用习惯,但你需要自己保证LibreOffice等外部依赖已经安装好,否则格式转换类功能会报错。我建议除非你已经熟悉Java环境的配置,否则还是走Docker路线最省心,尤其是Windows机器自己手工凑依赖比较麻烦。
3. 高频功能实操记录:拆分合并、转换、OCR与加水印
3.1 PDF拆分合并:企业里最常见的两个操作
Stirling PDF界面左侧导航会按功能类别排列,选择 Tools 下对应的 Merge 或 Split 功能。
说说合并。我处理最多的情况是有些人扫描文件时是一张张图片转成单独PDF的,十几份PDF要合成一个完整附件发送。直接在Merge页面把文件拖入,拖动调整顺序,点击提交,几秒后生成合并后的文件。它底层是把PDF每一页解析后重新组合,所以不管每个源文件页面的纸张大小是否一致,都能正常合并。唯一要提醒的是,如果原文件本身加了复杂的加密或权限保护,合并前需要先解除密码。
拆分功能同样有两种模式。一种是按固定页数拆分,比如两页拆一个文件,适合把一份长文档切分成多个小文件分发;另一种是指定某一页为边界,比如把合同的扫描页和发票扫描页拆开。操作时输入起始页和结束页即可。有一次我拿到一份200多页的投标文件扫描件,只需要把其中技术偏离表那几页发给厂家确认,就是用这个功能精确提取第84页到第89页,生成了一个独立小文件,非常方便。
这里有个细节值得注意:上传大文件时要观察服务器日志,如果长时间没有反应,先检查是否触发了容器内存上限或上传文件大小限制,后面第五部分会展开说明排查方法。
3.2 PDF转换:从PDF到Word、图片、HTML
转换是另一个高频需求。Stirling PDF 支持把PDF转换成Word、Excel、PowerPoint、图片等格式,也支持把图片合成PDF。
如果你的PDF是天生文字版,用普通“PDF转Word”功能就够了,转换质量很高,保留基础排版和段落结构。但如果你拿到的是扫描件,文字其实是“图片”形式,直接转Word只会得到一张无法编辑的大图。这时候要先走OCR识别流程,生成带文字层的PDF,再做转换。
从实际体验来看,中文文档转换时,字体映射偶尔会造成排版错乱,比如原始文档用的特殊字体系统里没有,会自动替换成默认字体。要减少出错,源PDF最好在生成时嵌入所有字体,也就是PDF里的文字不做字体子集化,这样转换时的信息丢失会少很多。
3.3 OCR中文识别:扫描件变成可编辑文本的关键一步
这个功能是我的刚需。我做项目时经常收到客户从纸质文件扫描过来的PDF,看起来是一页页图片,无法搜索里面的关键词,更别提复制内容。Stirling PDF自带的OCR功能帮了大忙。
但第一次使用时我踩了坑。默认镜像里只带了英文语言包,我直接对中文扫描件调用OCR,识别出来的内容全是乱码或直接识别不了。问题在于OCR引擎 Tesseract 不认识中文,要想让它识别中文,需要下载 chi_sim.traineddata 中文简体训练数据文件,放到 /usr/share/tessdata 目录下。
我在宿主机的工作目录里创建了 trainingData 文件夹,因为docker-compose里已经把该目录映射到容器内的 /usr/share/tessdata。下载方式:
bash复制# 进入docker-compose.yml所在目录
mkdir -p trainingData
cd trainingData
# 下载中文简体训练数据
wget https://github.com/tesseract-ocr/tessdata_best/raw/main/chi_sim.traineddata
# 建议同时下载中文繁体、英文,以备不时之需
wget https://github.com/tesseract-ocr/tessdata_best/raw/main/chi_tra.traineddata
wget https://github.com/tesseract-ocr/tessdata_best/raw/main/eng.traineddata
下载完成后重启容器:
bash复制docker compose restart
之后在OCR页面选择识别语言为 chi_sim,中文识别结果还是比较理想的,印刷体的识别准确率能到很高水平,对于扫描质量好的文档基本可用。注意上传的扫描件尽量保持原始分辨率,低于150dpi的图片识别率会掉得比较快。
3.4 水印功能与PDF安全:给内部文档打上专属标记
水印有两类需求:给“别人的PDF加水印”和“去除已有水印”。前者在Stirling PDF里很简单,在 Watermark 功能中,你可以选择文字水印还是图片水印。文字水印支持自定义内容、字体大小、颜色、透明度、旋转角度、平铺或居中模式等,参数很灵活。我常用的是给内部审核版本的方案书添加“内部材料,禁止外传”的平铺水印,字体设置成浅灰色加透明度,既不影响阅读,又能有效防止截图外传后无法追溯。
图片水印则适合把公司Logo打到每个页面角落,这个在投标文件或报价单里非常实用,设置好水平偏移和垂直偏移后,所有页面自动加上Logo。
关于去除水印功能,我说两句实话。这个功能确实存在,它属于“半去除”思路——对某些加在文字上方、经过简单混合的水印图像效果还行,但也容易损伤原页面内容。它的合理应用场景是处理你自己收到的测试稿件,或者公司内部误操作添加了水印的文件,而不是用来帮人编辑他人加密的合同或版权受保护的材料。把这类功能用在对的地方,工具才是真正帮到你。
3.5 压缩与页面编辑:日常处理的补充操作
Stirling PDF里有压缩功能,它其实是调用Ghostscript来优化PDF内部对象的存储结构,从而降低文件体积。PDF扫描件如果不做压缩,单页A4彩色扫描可能达到1MB以上,一个几十页的标书就是几十MB,发邮件很困难。我通常用压缩把这类扫描件压到原体积的一半到三分之一,肉眼几乎看不出画质损失。要注意的是,如果扫描件内容本身就是高密度文字,压缩率会有限,这是正常现象,文字边缘信息复杂,强行高压缩会糊。
另外一些页面操作类功能也很顺手,比如旋转页面方向、调整页面大小、按页面提取图片等,你把这些功能理解成一个“精简版在线Acrobat”,大部分日常工作就足够了。
4. 服务部署后的安全加固与内网使用细节
4.1 别以为自部署就等于绝对安全
如果你把Stirling PDF暴露到公网IP上,同时没有给页面加任何访问控制,那风险就来了。扫描器会定期扫描全网的开放端口,8080这种常见Web端口更是重灾区。虽然PDF工具本身不直接存储敏感文件,但如果被别有用心的人利用,把容器作为跳板机,或者利用旧版本漏洞发起攻击,都是隐患。
所以我的建议是:部署在内网时,默认只监听内网IP;如果必须要公网访问,一定加反向代理和认证层,不要直接把容器的8080端口暴露出去。
4.2 开启内置登录认证,不要用默认账号密码
Stirling PDF从较新版本起增加了基础登录认证能力。把docker-compose里的环境变量设置成:
yaml复制environment:
- DOCKER_ENABLE_SECURITY=true
默认情况下会生成一个随机账号密码输出在容器日志里,首次启动时记得查看:
bash复制docker logs stirling-pdf | grep -i password
用日志里的账号登录后,到后台修改成你自己的用户名和密码。如果你已经有公司内部的统一身份认证系统,也可以配置OAuth2或者LDAP对接,具体配置项目在界面的Settings里都能找到。别只图方便不设防,给工具加一个口令,能挡住90%的无聊扫描流量。生产环境需谨慎,即便是内部小工具,密码安全也是底线。
提示:如果你用旧版本没找到登录设置,建议升级到最新镜像,新版对认证的支持和安全性都做了不少改进。
4.3 用Nginx做反向代理并加一层访问控制
推荐架构是:用户访问域名或固定端口 -> Nginx -> Stirling PDF容器。这样可以在Nginx层做访问认证和HTTPS加密,也能方便地统一管理证书。我给出一个最小可用的Nginx配置片段:
nginx复制server {
listen 443 ssl http2;
server_name pdf.example.com;
ssl_certificate /etc/nginx/ssl/example.pem;
ssl_certificate_key /etc/nginx/ssl/example.key;
client_max_body_size 200M;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 限制只有内网IP段可以访问该服务
allow 192.168.1.0/24;
deny all;
}
}
其中 client_max_body_size 200M 很关键,默认Nginx上传限制通常只有1MB左右,不调大就会导致大PDF文件上传失败,页面永远没反应。如果你有更大文件处理需求,按实际情况把数值调高。
4.4 容器资源限制和日志滚动
部署在长期运行的服务器上,我建议给容器追加资源限制,避免极端情况下PDF处理占用全部CPU导致服务器卡死。可以在 docker-compose.yml 的 deploy 节点里配置,也可以直接 docker run 时加参数:
yaml复制deploy:
resources:
limits:
cpus: "2.0"
memory: 2g
同时给日志加上滚动策略。如果不限制,容器日志日积月累可能会占用大量磁盘,我自己遇到过几次服务器磁盘爆掉的情况,排查半天才发现是某个容器日志疯狂输出。
yaml复制logging:
driver: "json-file"
options:
max-size: "20m"
max-file: "5"
5. 常见问题与排查实录
5.1 页面打开正常,但点某个功能一直转圈没结果
优先查看容器日志,这是最直接的排查手段:
bash复制docker logs -f stirling-pdf
遇到过一种情况是服务器内存只有1GB,处理大型PDF时Java堆内存溢出,日志里能看到 OutOfMemoryError。这很好解决,给容器加内存限制或者给宿主机增加Swap。如果你的文件不是特别大,2GB内存跑日常任务就足够,处理50MB以上的大文件时内存占用会比较明显。
另外注意上传文件大小限制。若你配置了Nginx反向代理且没设置 client_max_body_size,文件会传不上去。默认Nginx限制是1MB,上传大文件就会前功尽弃,务必按需调整。
5.2 OCR识别中文不出来,识别结果乱码
这是新手最容易遇到的问题,和我说过的一样,多半是 tessdata 里没有中文训练数据。进入容器检查:
bash复制docker exec -it stirling-pdf ls /usr/share/tessdata
看看里面有没有 chi_sim.traineddata。没有的话,按照本文第二部分的方法下载并挂载到容器里,重启后就会在OCR页面看到简体中文选项。如果已经下载了还是识别差,注意扫描件分辨率和倾斜角度。质量差的扫描件建议先用图像预处理功能纠偏、增强对比度后再OCR。
5.3 文件转换时窗口一直显示“正在处理”或服务崩溃
可能原因有几种,常见的是LibreOffice进程在容器内崩溃。处理方式是先重启容器:
bash复制docker compose restart
如果经常出现转换失败,尝试不使用最新版本镜像而是固定某个版本。这种Web工具的功能频繁更新,有时候新版本会引入回归问题。我在生产环境一般会固定一个已验证过的版本号,而不是一直用 latest 标签。
5.4 安装完界面全英文,找不到中文入口
由于默认镜像内置的语言可选显示项可能没有中文,需要在环境变量 LANGS 里加入 zh_CN,然后重启容器。之后进入界面的右上角个人中心或设置选项里,把显示语言切换为中文。如果切换后部分页面还有英文属于正常现象,大多数核心功能标签都会随界面语言变化。
5.5 处理大文件时磁盘空间不够
当合并或转换几百MB的大文件时,容器会在工作目录生成临时文件,并对源文件做中间态处理。如果磁盘剩余空间不足,任务会静默失败,页面上只提示“处理失败”。排查方法很简单,在宿主机执行 df -h 查看磁盘使用率,清理多余镜像和旧的构建缓存,保证至少有2倍于源文件大小的空闲空间。
5.6 旧版升级后自定义设置丢失
升级做法是拉取新镜像,重建容器:
bash复制docker compose pull
docker compose up -d
但很多用户升级完发现之前配的界面语言、主题等设置全丢了。这是因为某些早期版本把设置存在容器内部,容器一旦重建数据就丢失。如果你用的是新版镜像,配置存在 /configs 目录,只要docker-compose里挂载了 ./extraConfigs:/configs,设置就会保留。所以从一开始部署时就把卷挂载好,事后再补挂载有时反而麻烦。
注意:升级前建议备份整个工作目录,尤其是含有你后期放置的语言包和自定义配置的目录,做好回滚预案。
6. 使用心得和后续扩展建议
写到这里,想多说几句自己的体验。
我在实际使用中发现,自部署这种“PDF处理工具”带给我的最大便利不是省了一点点软件费用,而是把“文件处理”这件事彻底变成了一个可靠的服务。之前处理PDF文件,我得打开一个网站,上传、下载、关闭,如果处理多个文件,浏览器里能开十几二十个标签页。现在公司内网部署了一个Stirling PDF,同事们遇到合并合同、压缩扫描件、给PDF加水印这些需求,直接打开内网网页就能解决,文件不用传外网,也不用安装任何客户端。从“工具”变成“服务”之后,使用频率和效率都提高了很多。
另外一个小技巧:如果你的团队经常需要API方式处理PDF,Stirling PDF也提供了对应的API接口,开发同事可以用脚本调用,实现自动化批量处理。比如每晚定时把一个目录下的多个PDF自动合并并添加水印,然后归档到指定位置,这就是把一个人手工半小时的重复工作交给了机器。
最后说一个经验。这类工具我并不建议追新求快,每次更新先看Release Notes,确认新功能或修复确实是你需要的再升级。生产中稳定优先,版本升得太勤反而会增加排查成本。我个人现在的做法是部署一个长期稳定版本供日常使用,然后偶尔用新镜像在测试环境里试玩,确认没问题再考虑切换。
如果你也想在公司内部或个人服务器上彻底解决PDF处理问题,完全可以照着上面的步骤搭一套起来。无论是用于替代在线PDF网站,还是统一解决团队协作时遇到的PDF需求,都很合适,这也是我用过之后的真实结论。
