Yii框架需借助smalot/pdfparser等第三方库实现PDF文本提取,推荐安装该库并封装为PdfTextExtractor组件,在控制器中调用extract方法提取纯文本或分页结构化内容。

Yii 框架本身不内置 PDF 文本提取功能,需借助第三方 PHP 库(如 smalot/pdfparser、setasign/fpdi 或 spipu/html2pdf 的解析扩展)配合 Yii 的组件机制来封装使用。核心思路是:选一个稳定、支持中文(含字体映射与编码处理)的 PDF 解析库,将其注册为 Yii 组件,再在控制器或服务中调用。
选择并安装合适的 PDF 解析库
推荐使用 smalot/pdfparser,它轻量、纯 PHP 实现、支持多页文本提取,对基础中文 PDF(尤其是含内嵌字体或 UTF-8 编码文本)兼容性较好。
- 执行命令安装:composer require smalot/pdfparser
- 确认项目已启用 mbstring 和 iconv 扩展(中文解析必需)
- 若 PDF 含扫描图像或 OCR 内容,该库无法提取——需先用 Tesseract + imagick 预处理,不属于本组件范畴
封装为 Yii 组件(以 Yii2 为例)
在 @app/components 下新建 PdfTextExtractor.php:
namespace app\components;
use Smalot\PdfParser\Parser;
class PdfTextExtractor
{
public function extract($filePath): string
{
if (!is_file($filePath) || !is_readable($filePath)) {
throw new \InvalidArgumentException("PDF file not accessible: $filePath");
}
$parser = new Parser();
try {
$pdf = $parser->parseFile($filePath);
$text = $pdf->getText(); // 自动合并所有页文本
// 可选:清理多余空白与换行
return preg_replace('/\s+/', ' ', trim($text));
} catch (\Exception $e) {
throw new \RuntimeException("Failed to parse PDF: " . $e->getMessage());
}
}
}
然后在 config/web.php 中注册组件:
'components' => [
'pdfExtractor' => [
'class' => 'app\components\PdfTextExtractor',
],
],
在控制器中调用提取文本
示例:接收上传的 PDF 文件并返回纯文本内容
use yii\web\UploadedFile;
public function actionExtract()
{
$model = new UploadForm(); // 假设你有文件上传表单模型
if (Yii::$app->request->isPost) {
$model->file = UploadedFile::getInstance($model, 'file');
if ($model->file && $model->file->extension === 'pdf') {
$tempPath = $model->file->tempName;
try {
$text = Yii::$app->pdfExtractor->extract($tempPath);
return $this->asJson(['success' => true, 'text' => $text]);
} catch (\Exception $e) {
return $this->asJson(['success' => false, 'error' => $e->getMessage()]);
}
}
}
return $this->render('upload');
}
注意点:
- 确保临时文件路径可读;生产环境建议校验文件 MIME 类型(application/pdf),不止依赖后缀
- 大 PDF(>20MB 或 >500 页)可能触发内存限制,可在 php.ini 调高 memory_limit 和 max_execution_time
- 若文本乱码,大概率是 PDF 使用了未映射的中文字体;可尝试用 $pdf->getDetails() 查看字体信息,或改用支持字体回退的库如 tcpdf-parser
进阶:按页提取与结构化返回
如需保留页码结构,可改用 $pdf->getPages() 遍历:
$pages = [];
foreach ($pdf->getPages() as $index => $page) {
$pages[] = [
'page' => $index + 1,
'text' => preg_replace('/\s+/', ' ', trim($page->getText())),
];
}
return $pages;
这样返回 JSON 就包含分页字段,便于前端做高亮或定位。



















