Поиск в PDF для строк и получить их положение на странице - PullRequest
0 голосов
/ 11 июня 2018

Я хотел бы добавить именованные места в местоположения существующего PDF-файла, которые задаются некоторой строкой (скажем: поместите именованный в первый вхождение строки "Глава 1").Затем я хотел бы иметь возможность перейти к этим именованным событиям, используя события JS.

Чего я достиг на данный момент, используя PHP и FPDF / FPDI: я ​​могу загрузить существующий PDF с помощью FPDI и добавить именованные дескрипторы в произвольные позиции, используяслегка измененная версия [1].Затем я могу встроить PDF-файл в iframe и перейти к именованным дестам, используя, например, кнопки JS.

Однако пока мне нужно выяснить положение именованных дест вручную.Как я могу найти в PDF строки и получить номера страниц и позиции результатов поиска, чтобы я мог добавить именованные места там?

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

1 Ответ

0 голосов
/ 13 июня 2018

Невозможно проанализировать содержимое документа PDF с помощью FPDI.

У нас (Setasign - автор FPDI и PDF_NamedDestitions) есть продукт (не бесплатный), который позволяет вам выполнять эту задачу:Компонент 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
...
...