Zend Lucene和PDF文档第1部分:PDF元数据

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元数据

查看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元数据

首先,我们将创建一个表单,该表单将允许我们编辑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部分:结论