Zend Lucene是强大的搜索引擎,但需要进行一些设置才能使其正常运行。我过去无法启动和运行的一件事是索引和搜索PDF文档。此处的困难在于,如何轻松轻松地为PDF文档的内容编制索引尚不清楚。我遇到了几个可以尝试的功能,但是即使这样不起作用,也可以使用Zend_Pdf库创建和编辑PDF元数据。因为这个主题有很多内容,所以我认为我会分多个部分创建博客文章。对于这篇文章,我将研究如何添加和编辑此元数据。该元数据可用于对您的PDF文档进行分类,并允许您对其进行索引,并使用Zend Lucene提供体面的搜索解决方案。
在我们对文件执行任何操作之前,我们需要将它们列出来,以便我们可以对其进行访问。您可以使用任何喜欢的方法来执行此操作,但是以下代码使用glob为您获取PDF文件列表并将其发送到视图。本示例还使用了一个配置值,该值指向包含我们的PDF文件的目录。
$config = Zend_Registry::get('config'); $globOut = glob($config->filesDirectory . '*.pdf'); if (count($globOut) > 0) { // 确保glob数组中有东西 $files = array(); foreach ($globOut as $filename) { $files[] = $filename; } $this->view->files = $files; } else { $this->view->message = 'No files found.<br />'; }
视图可能看起来像这样。
<?php if ($this->message) { echo $this->message; } if (is_array($this->files)) { echo '<ul>'; foreach ($this->files as $file) { echo '<li>'.$file. ' <a href="'.$this->url(array('controller'=>'pdf', 'action'=>'viewmeta', 'file' => urlencode($file)),'default', true).'" title="View PDF Meta">View Meta</a>' . ' <a href="'.$this->url(array('controller'=>'pdf', 'action'=>'editmeta', 'file' => urlencode($file)),'default', true).'" title="Edit PDF Meta">Edit Meta</a>' .'</li>'; } echo '</ul>'; }
查看PDF元数据非常容易,尤其是使用Zend_Pdf对象。第一步是将PDF加载到Zend_Pdf类可以使用的数据结构中。第二步是通过使用Zend_Pdf对象的properties数组来提取您感兴趣的属性。下面的代码示例是一个从控制器执行的操作,该控制器将从PDF文档(由$metaValues数组分配)中提取所有需要的元数据,并将它们传递给视图以进行打印。PDF文档的位置被编码(使用urlencode)到URL作为文件属性。properties数组是一个公共的关联数组,允许您存储和检索元数据信息。并非总是会设置每个元数据值,因此在尝试访问该键之前,我们首先确保该键存在于属性数组中。
public function viewmetaAction() { $pdfPath = urldecode($this->_request->getParam('file')); $pdf = Zend_Pdf::load($pdfPath); $metaValues = array('Title' => '', 'Author' => '', 'Subject' => '', 'Keywords' => '', 'Creator' => '', 'Producer' => '', 'CreationDate' => '', 'ModDate' => '', ); foreach ($metaValues as $meta => $metaValue) { if (isset($pdf->properties[$meta])) { $metaValues[$meta] = $pdf->properties[$meta]; } else { $metaValues[$meta] = ''; } } $this->view->file = $pdfPath; $this->view->metaValues = $metaValues; }
$metaValues数组包含许多键,这些键被Zend_Pdf用作标准的元数据信息集。有关默认值的更多信息,请参见Zend Framework网站上的Zend_Pdf元数据信息。完全可以根据需要创建任意多个值,并将其添加到其他元数据信息中。我将在下一节中编辑元数据的地方进行介绍。我也将相关的动作视图创建留给读者,因为它应该不太难。
首先,我们将创建一个表单,该表单将允许我们编辑PDF文档的元数据。该表单仅包含一个项目(标题),但添加其他项目并非难事,只需复制并粘贴title元素并更改参数即可满足您的需求。在这里使用表单很有用,因为我们可以使用Zend Form的内置表单验证功能来防止用户将愚蠢的数据输入到我们的PDF中。唯一要确保的是每个字段的名称(第二个参数)与元数据键的名称匹配。
class Form_PdfMeta extends Zend_Form { public function init() { // 将显示表单的方法设置为POST $this->setMethod('post'); // 添加文本区域元素作为标题。 $this->addElement('textarea', 'Title', array( 'label' => 'Title', 'required' => true, 'rows' => '10', 'cols' => '50', 'filters' => array('StringTrim'), 'validators' => array( array('validator' => 'StringLength', 'options' => array(0,500))) )); // 添加提交按钮 $this->addElement('submit', 'submit', array('label' => 'Save')); } }
现在,我们已经创建了表单,现在需要创建控制器动作,以允许我们编辑元数据。我没有遍历每一行并解释正在发生的事情,而是对代码进行了注释,以使其更易于理解。需要注意的一件事是,如果PDF文档不存在,会发生什么情况。您可能要向视图发出警告,将用户重定向到错误页面,或者简单地引发异常。但是,这是读者的练习。
SLASH常量包含一个跨平台目录斜杠,我之前已经写过。这有助于我们从URL字符串中找到文件的名称。
$metaValues数组包含要编辑的值的键。您可以在此处输入任意数量的元素,唯一的不足是您还需要为每个条目创建表单元素。比较冒险的您可以创建一个表单类,该表单类围绕此数组中的元素构建表单。
public function editmetaAction() { // 获取表单并发送到视图。 $form = new Form_PdfMeta(); $this->view->form = $form; // 获取文件并将位置发送到视图。 $pdfPath = urldecode($this->_request->getParam('file')); $file = substr($pdfPath, strrpos($pdfPath, SLASH)+1); $this->view->file = $file; // 定义我们正在查看的元数据。 $metaValues = array('Title' => ''); if ($this->_request->isPost()) { // 获取当前表单值。 $formData = $this->_request->getPost(); if ($form->isValid($formData)) { // 表单值有效。 // 将表单的内容保存到PDF中关联的元数据字段中。 $pdf = Zend_Pdf::load($pdfPath); foreach ($metaValues as $meta => $metaValue) { if (isset($formData[$meta])) { $pdf->properties[$meta] = $formData[$meta]; } else { $pdf->properties[$meta] = ''; } } $pdf->save($pdfPath); // 将用户重定向到此控制器的列表操作。 return $this->_helper->redirector('list', 'pdf', '', array())->setCode(301); } else { // 表单值无效,将当前值发送到表单。 $form->populate($formData); } } else { // 在开始执行任何操作之前,请确保该文件存在。 if (file_exists($pdfPath)) { // 从PDF文档中提取任何当前的元数据值 $pdf = Zend_Pdf::load($pdfPath); foreach ($metaValues as $meta => $metaValue) { if (isset($pdf->properties[$meta])) { $metaValues[$meta] = $pdf->properties[$meta]; } else { $metaValues[$meta] = ''; } } // 填写不包含元数据值的表单。 $form->populate($metaValues); } else { // 文件不存在。 } } }
我们对该操作的看法将类似于以下代码块。该视图将在左侧打印表格(注意在操作期间分配的所有值),并在右侧显示PDF的视图。这意味着我们的用户将能够看到他们正在编辑其元数据的PDF文档,这将有助于提供良好的搜索服务。
<div style="float:left;width:39%;"> <?php echo $this->form; ?> </div> <iframe xx_src="<?php echo $this->baseUrl();?>/files/<?php echo $this->file; ?>" width="60%" style="height:50em" align="right" ></iframe>
的确如此,如果您想要该项目的所有源代码,我将在上一篇文章中将其作为可下载的zip文件发布,因此请继续关注它。
在下一篇Zend Lucene和PDF Documents帖子中,我将研究如何提取PDF文档的内容,以便我们也可以将其与元数据一起编制索引。
Zend Lucene和PDF文档第1部分:PDF元数据
Zend Lucene和PDF文档第2部分:PDF数据提取
Zend Lucene和PDF文档第3部分:为文档建立索引
Zend Lucene和PDF文档第4部分:搜索
Zend Lucene和PDF文档第5部分:结论