php+yii本身不支持pdf文本提取,需依赖外部工具;推荐使用系统级pdftotext(poppler-utils),兼顾中文字体、加密与排版兼容性,并在控制器中封装安全调用逻辑。

PHP + Yii 框架本身不提供 PDF 文本提取能力,它擅长生成 PDF(如用 mPDF、yii2-export),但读取/解析 PDF 内容需依赖外部工具或库。直接在 Yii 项目里“获取 PDF 文本内容”,核心是调用成熟可靠的解析方案,并将其封装进控制器或服务层。下面给出一个真实可用、兼顾健壮性与可维护性的完整示例。
前提:确保系统支持 pdftotext(推荐方案)
这是目前在 Yii 环境下最稳定、兼容性最好的方式——尤其对含中文字体、简单加密、多页排版的 PDF 效果远超纯 PHP 库。
- Linux(Ubuntu/Debian):
sudo apt install poppler-utils - macOS:
brew install poppler - 确认 PHP 可执行命令:
exec('which pdftotext', $out);应返回路径 - 检查
disable_functions是否禁用了exec或shell_exec
Yii 控制器中封装 PDF 提取逻辑
在 controllers/PdfController.php 中添加方法:
<?php namespace app\controllers;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\helpers\FileHelper;
class PdfController extends Controller
{
public function actionExtractText($path = null)
{
// 支持传入相对路径(如 'uploads/invoice.pdf')或 URL(需先下载)
if (empty($path)) {
throw new NotFoundHttpException('PDF 路径未提供');
}
$pdfPath = \Yii::getAlias('@webroot/') . ltrim($path, '/');
// 防止路径遍历
if (!is_file($pdfPath) || !FileHelper::validatePath($pdfPath)) {
throw new NotFoundHttpException('PDF 文件不存在或路径非法');
}
// 使用 pdftotext 提取(-layout 保格式,-enc UTF-8 防中文乱码)
$txtPath = tempnam(sys_get_temp_dir(), 'pdf2txt_') . '.txt';
$cmd = sprintf(
'pdftotext -layout -enc UTF-8 %s %s 2>/dev/null',
escapeshellarg($pdfPath),
escapeshellarg($txtPath)
);
exec($cmd, $output, $returnCode);
if ($returnCode !== 0 || !file_exists($txtPath)) {
@unlink($txtPath);
throw new \Exception('PDF 文本提取失败,请检查文件是否加密或损坏');
}
$text = file_get_contents($txtPath);
@unlink($txtPath);
return $this->asJson(['success' => true, 'text' => trim($text)]);
}
}
访问示例:/index.php?r=pdf/extract-text&path=uploads%2Freport.pdf
处理加密 PDF(可选增强)
若 PDF 含所有者密码(常见于银行账单、电子发票),需提前解密。可在上一步前插入检测与解密逻辑:
// 检查是否加密
$checkCmd = sprintf('pdfinfo %s 2>&1 | grep -i "Encrypted:"', escapeshellarg($pdfPath));
exec($checkCmd, $infoLines, $infoCode);
$isEncrypted = !empty($infoLines) && stripos(implode('', $infoLines), 'yes') !== false;
if ($isEncrypted) {
$decryptedPath = tempnam(sys_get_temp_dir(), 'decrypted_') . '.pdf';
// 尝试空密码解密(部分弱加密有效)
$qpdfCmd = sprintf('qpdf --password="" --decrypt %s %s 2>/dev/null',
escapeshellarg($pdfPath), escapeshellarg($decryptedPath));
exec($qpdfCmd, $qpdfOut, $qpdfCode);
if ($qpdfCode === 0 && file_exists($decryptedPath)) {
$pdfPath = $decryptedPath;
// 注意:记得在 finally 块中 unlink($decryptedPath)
}
}
替代方案:使用 ComPDFKit API(免服务器依赖)
适合无法安装系统工具、需处理扫描件(OCR)或高精度结构化提取的场景。在控制器中调用其 REST 接口:
- 注册获取
publicKey/secretKey(官网 compdf.com) - 先请求 token,再上传 PDF 并轮询结果
- 响应 JSON 中
data.text即为提取文本 - 注意:涉及网络请求和异步任务,需加超时与错误重试
该方式无需服务器权限,但有调用量限制和延迟,适合低频、高质需求。
不复杂但容易忽略:纯 PHP 库(如 smalot/pdfparser)在 Yii 里也能用,但遇到字体嵌入、JBIG2 压缩、扫描件就基本失效;而 pdftotext 是工业级工具,配合 Yii 的路径管理与异常处理,就能稳稳落地。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











