yii不支持解析加密pdf,需借助qpdf等外部工具解密后再用smalot/pdfparser提取文本;须验证是否真为密码加密、过滤用户输入、及时清理临时文件。

Yii 本身不提供解析加密 PDF 的能力,也不内置 PDF 文本提取功能。PDF 加密(尤其是带密码的)属于底层文档处理范畴,需依赖外部库完成解密 + 解析两步操作,Yii 只负责调用和整合。
先确认 PDF 是否真的被密码加密
不是所有“打不开”的 PDF 都是加密的——可能是权限限制(如禁止复制)、损坏、或仅用 JavaScript 保护。用命令行工具快速验证:
- Linux/macOS 下运行:
pdfinfo -meta your_file.pdf,若输出含 Encrypted: yes,说明启用了密码保护 - Windows 可用 qpdf --show-encryption file.pdf(需提前安装 qpdf)
- 若提示“Permission denied”但无加密标识,大概率是权限锁,非密码锁,文本提取仍可进行
PHP 层需引入支持密码解密的 PDF 库
原生 PHP 扩展(如 pdflib)不支持解密;tcpdf 和 dompdf 也不支持。必须选用能处理加密 PDF 的库:
- Smalot/pdfparser:轻量,支持 Owner/ User 密码解密(需手动传入密码),但对 AES-256 或新版 Adobe 加密支持有限
- setasign/fpdi + setasign/tcpdf 组合:FPDI 可导入加密 PDF(需配合 TCPDF 的解密逻辑),但仅支持较老的 RC4 加密
-
更稳妥的选择是调用系统级工具:如
qpdf --decrypt --password=xxx input.pdf output.pdf,再用通用解析库读取 output.pdf
在 Yii 控制器中可这样调用(注意校验密码和错误输出):
$password = '123456';
$inputPath = '@app/files/protected.pdf';
$outputPath = '@app/runtime/decrypted.pdf';
$cmd = sprintf('qpdf --decrypt --password=%s %s %s 2>&1',
escapeshellarg($password),
escapeshellarg(Yii::getAlias($inputPath)),
escapeshellarg(Yii::getAlias($outputPath))
);
exec($cmd, $output, $returnCode);
if ($returnCode !== 0) {
throw new \Exception('PDF 解密失败:' . implode("\n", $output));
}
解密后提取文本内容
解密成功后得到普通 PDF,可用以下方式提取文字:
- 继续用 Smalot/pdfparser(推荐):它不依赖扩展,纯 PHP 实现,支持多页文本提取
- 示例代码:
use Smalot\PdfParser\Parser; $pdf = new Parser(); $document = $pdf->parseFile(Yii::getAlias($outputPath)); $text = $document->getText(); // 返回全部页面纯文本
- 如需保留结构(如按页、按块),可用
$document->getDetails()或遍历$document->getPages() - 注意:扫描版 PDF(图片型)无法提取文字,需先 OCR;该库只处理可选中文本的 PDF
安全与部署提醒
生产环境慎用 exec 调用 qpdf,需确保:
- qpdf 已安装且在系统 PATH 中(Ubuntu:
apt install qpdf) - PHP 进程有读写
@app/runtime目录权限 - 用户输入的密码必须过滤(避免 shell 注入),务必用
escapeshellarg() - 敏感文件解密后应立即 unlink,避免残留











