【问题标题】:Search PDF for strings and get their position on the page在 PDF 中搜索字符串并获取它们在页面上的位置
【发布时间】:2018-06-11 16:17:55
【问题描述】:

我想将 nameddest 添加到由某个字符串指定的现有 PDF 的位置(例如:在字符串“Chapter 1”的第一次出现处放置一个 nameddest)。然后我希望能够使用 JS 事件跳转到那些命名的目的地。

到目前为止,我使用 PHP 和 FPDF/FPDI 所取得的成就:我可以使用 FPDI 加载现有的 PDF,并使用 [1] 的略微修改版本将 nameddests 添加到任意位置。然后我可以将 PDF 嵌入到 iframe 中,并使用例如 JS 按钮导航到 nameddest。

但是,到目前为止,我需要手动找出 nameddest 的位置。如何在 PDF 中搜索字符串并获取搜索结果的页码和位置,以便在其中添加 nameddest?

[1]http://www.fpdf.org/en/script/script99.php

【问题讨论】:

    标签: php pdf search fpdf


    【解决方案1】:

    用 FPDI 分析 PDF 文档的内容是不可能的。

    我们(Setasign - FPDI 和 PDF_NamedDestinations 的作者)有一个产品(不是免费的)可让您处理此任务:SetaPDF-Extractor 组件。

    您项目的简单 POC 可能如下所示:

    <?php
    // load and register the autoload function
    require_once('library/SetaPDF/Autoload.php');
    
    $writer = new SetaPDF_Core_Writer_Http('result.pdf', true);
    $document = SetaPDF_Core_Document::loadByFilename('file/with/chapters.pdf', $writer);
    
    $extractor = new SetaPDF_Extractor($document);
    
    // define the word strategy
    $strategy = new SetaPDF_Extractor_Strategy_Word();
    $extractor->setStrategy($strategy);
    
    // get the pages helper
    $pages = $document->getCatalog()->getPages();
    
    // get access to the named destination tree
    $names = $document
        ->getCatalog()
        ->getNames()
        ->getTree(SetaPDF_Core_Document_Catalog_Names::DESTS, true);
    
    for ($pageNo = 1; $pageNo <= $pages->count(); $pageNo++) {
        /**
         * @var SetaPDF_Extractor_Result_Word[] $words
         */
        $words = $extractor->getResultByPageNumber($pageNo);
    
        // iterate over all found words and search for "Chapter" followed by a numeric string...
        foreach ($words AS $word) {
            $string = $word->getString();
            if ($string === 'Chapter') {
                $chapter = $word;
                continue;
            }
    
            if (null === $chapter) {
                continue;
            }
    
            // is the next word a numeric string
            if (is_numeric($word->getString())) {
                // get the coordinates of the word
                $bounds = $word->getBounds()[0];
                // create a destination
                $destination = SetaPDF_Core_Document_Destination::createByPageNo(
                    $document,
                    $pageNo,
                    SetaPDF_Core_Document_Destination::FIT_MODE_FIT_BH,
                    $bounds->getUl()->getY()
                );
    
                // create a name (shall be unique)
                $name = strtolower($chapter . $word->getString());
                try {
                    // add the named destination to the name tree
                    $names->add($name, $destination->getPdfValue());
                } catch (SetaPDF_Core_DataStructure_Tree_KeyAlreadyExistsException $e) {
                    // handle this exception
                }
            }
    
            $chapter = null;
        }
    }
    
    // save and finish the resulting document
    $document->save()->finish();
    

    然后您可以通过这种方式通过 URL 访问命名的目的地(查看器应用程序和浏览器插件需要支持):

    http://www.example.com/script.php#chapter1
    http://www.example.com/script.php#chapter2
    http://www.example.com/script.php#chapter10
    ...
    

    【讨论】:

    • 是否有可用的试用版以确保它适用于我们的示例
    • 好的,请看here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-07
    • 2019-07-08
    • 1970-01-01
    相关资源
    最近更新 更多