Получить количество страниц в документе PDF
Этот вопрос для ссылки и сравнения. Решение - принятый ответ ниже.
Много часов я искал быстрый и простой, но в основном точный способ получения количества страниц в документе PDF. Поскольку я работаю в компании по печати и печати графики, которая много работает с PDF файлами, количество страниц в документе должно быть точно известно до их обработки. Документы PDF поступают от разных клиентов, поэтому они не создаются в одном приложении и/или не используют один и тот же метод сжатия.
Вот некоторые из ответов, которые я нашел недостаточными или просто НЕ работающими:
Использование Imagick (расширение PHP)
Imagick требует большой установки, apache нужно перезапустить, и когда у меня наконец-то все заработало, обработка заняла удивительно много времени (2-3 минуты на каждый документ), и он всегда возвращал 1
страницу в каждом документе (не видел работающего копия Imagick до сих пор), поэтому я выбросил ее. Это было как с getNumberImages()
и identifyImage()
методов.
Использование FPDI (библиотека PHP)
FPDI прост в использовании и установке (просто извлекает файлы и вызывает скрипт PHP), НО многие методы сжатия не поддерживаются FPDI. Затем он возвращает ошибку:
Ошибка FPDF: этот документ (test_1.pdf), вероятно, использует метод сжатия, который не поддерживается бесплатным анализатором, поставляемым с FPDI.
Открытие потока и поиск с помощью регулярного выражения:
Это открывает файл PDF в потоке и ищет какую-то строку, содержащую количество страниц или что-то подобное.
$f = "test1.pdf";
$stream = fopen($f, "r");
$content = fread ($stream, filesize($f));
if(!$stream || !$content)
return 0;
$count = 0;
// Regular Expressions found by Googling (all linked to SO answers):
$regex = "/\/Count\s+(\d+)/";
$regex2 = "/\/Page\W*(\d+)/";
$regex3 = "/\/N\s+(\d+)/";
if(preg_match_all($regex, $content, $matches))
$count = max($matches);
return $count;
-
/\/Count\s+(\d+)/
(ищет /Count <number>
) не работает, потому что только несколько документов имеют параметр /Count
внутри, поэтому большую часть времени он не возвращает что-нибудь. Источник. -
/\/Page\W*(\d+)/
(ищет /Page<number>
) не получает количество страниц, в основном содержит некоторые другие данные. Источник. -
/\/N\s+(\d+)/
(ищет /N <number>
) также не работает, так как документы могут содержать несколько значений /N
; большинство, если не все, не содержащие количество страниц. Источник.
Итак, что же работает надежно и точно?
Смотрите ответ ниже
Ответы
Ответ 1
Простой исполняемый файл командной строки: pdfinfo.
Загружается для Linux и Windows. Вы загружаете сжатый файл, содержащий несколько небольших программ, связанных с PDF. Извлеките его где-нибудь.
Один из этих файлов - pdfinfo (или pdfinfo.exe для Windows). Пример данных, возвращаемых при запуске в PDF-документе:
Title: test1.pdf
Author: John Smith
Creator: PScript5.dll Version 5.2.2
Producer: Acrobat Distiller 9.2.0 (Windows)
CreationDate: 01/09/13 19:46:57
ModDate: 01/09/13 19:46:57
Tagged: yes
Form: none
Pages: 13 <-- This is what we need
Encrypted: no
Page size: 2384 x 3370 pts (A0)
File size: 17569259 bytes
Optimized: yes
PDF version: 1.6
Я не видел PDF-документ, в котором он возвращал false pagecount (пока). Это также очень быстро, даже с большими документами в 200+ Мб время ответа составляет всего несколько секунд или меньше.
Существует простой способ извлечения pagecount из вывода, здесь, в PHP:
// Make a function for convenience
function getPDFPages($document)
{
$cmd = "/path/to/pdfinfo"; // Linux
$cmd = "C:\\path\\to\\pdfinfo.exe"; // Windows
// Parse entire output
// Surround with double quotes if file name has spaces
exec("$cmd \"$document\"", $output);
// Iterate through lines
$pagecount = 0;
foreach($output as $op)
{
// Extract the number
if(preg_match("/Pages:\s*(\d+)/i", $op, $matches) === 1)
{
$pagecount = intval($matches[1]);
break;
}
}
return $pagecount;
}
// Use the function
echo getPDFPages("test 1.pdf"); // Output: 13
Конечно, этот инструмент командной строки можно использовать на других языках, которые могут анализировать вывод из внешней программы, но я использую его в PHP.
Я знаю его не чистый PHP, но внешние программы лучше подходят для обработки PDF (как видно из вопроса).
Я надеюсь, что это может помочь людям, потому что я потратил много времени на то, чтобы найти решение этого вопроса, и я видел много вопросов о PDF-странице, в которых я не нашел ответ, который я искал, Вот почему я задал этот вопрос и сам ответил сам.
Ответ 2
Самое простое использование ImageMagick
вот пример кода
$image = new Imagick();
$image->pingImage('myPdfFile.pdf');
echo $image->getNumberImages();
в противном случае вы можете также использовать библиотеки PDF
, такие как MPDF
или TCPDF
для PHP
Ответ 3
если вы не можете установить дополнительные пакеты, вы можете использовать этот простой однострочный интерфейс:
foundPages=$(strings < $PDF_FILE | sed -n 's|.*Count -\{0,1\}\([0-9]\{1,\}\).*|\1|p' | sort -rn | head -n 1)
Ответ 4
Это, похоже, работает очень хорошо, без необходимости в специальных пакетах или выводе команды синтаксического анализа.
<?php
$target_pdf = "multi-page-test.pdf";
$cmd = sprintf("identify %s", $target_pdf);
exec($cmd, $output);
$pages = count($output);
Ответ 5
Если у вас есть доступ к оболочке, самым простым (но не используемым на 100% PDF файлах) подходом будет использование grep
.
Это должно возвращать только количество страниц:
grep -m 1 -aoP '(?<=\/N )\d+(?=\/)' file.pdf
Пример: https://regex101.com/r/BrUTKn/1
Описание переключателей:
-
-m 1
необходимо, так как некоторые файлы могут иметь более одного соответствия шаблону регулярных выражений (volonteer необходимо заменить это расширением для регулярного выражения только для соответствия)
-
-a
необходимо обработать двоичный файл как текст
-
-o
, чтобы показать только совпадение
-
-P
для использования регулярного выражения Perl
Объяснение Regex:
- начало "разделителя":
(?<=\/N )
lookbehind of /N
(символ пробела не отображается здесь)
- фактический результат:
\d+
любое количество цифр
- end "delimiter":
(?=\/)
lookahead /
Nota bene: если в некотором случае совпадение не найдено, безопасно предположить, что существует только одна страница.
Ответ 6
Так как вы можете использовать утилиты командной строки, вы можете использовать cpdf (Microsoft Windows/Linux/Mac OS X). Чтобы получить количество страниц в одном PDF:
cpdf.exe -pages "my file.pdf"
Ответ 7
Вы можете использовать qpdf
, как показано ниже. Если файл file_name.pdf содержит 100 страниц,
$ qpdf --show-npages file_name.pdf
100
Ответ 8
Вот функция R
, которая сообщает номер страницы файла PDF с помощью команды pdfinfo
.
pdf.file.page.number <- function(fname) {
a <- pipe(paste("pdfinfo", fname, "| grep Pages | cut -d: -f2"))
page.number <- as.numeric(readLines(a))
close(a)
page.number
}
if (F) {
pdf.file.page.number("a.pdf")
}
Ответ 9
Вот команда Windows script, используя gsscript, который сообщает номер страницы файла PDF
@echo off
echo.
rem
rem this file: getlastpagenumber.cmd
rem version 0.1 from commander 2015-11-03
rem need Ghostscript e.g. download and install from http://www.ghostscript.com/download/
rem Install path "C:\prg\ghostscript" for using the script without changes \\ and have less problems with UAC
rem
:vars
set __gs__="C:\prg\ghostscript\bin\gswin64c.exe"
set __lastpagenumber__=1
set __pdffile__="%~1"
set __pdffilename__="%~n1"
set __datetime__=%date%%time%
set __datetime__=%__datetime__:.=%
set __datetime__=%__datetime__::=%
set __datetime__=%__datetime__:,=%
set __datetime__=%__datetime__:/=%
set __datetime__=%__datetime__: =%
set __tmpfile__="%tmp%\%~n0_%__datetime__%.tmp"
:check
if %__pdffile__%=="" goto error1
if not exist %__pdffile__% goto error2
if not exist %__gs__% goto error3
:main
%__gs__% -dBATCH -dFirstPage=9999999 -dQUIET -dNODISPLAY -dNOPAUSE -sstdout=%__tmpfile__% %__pdffile__%
FOR /F " tokens=2,3* usebackq delims=:" %%A IN (`findstr /i "number" test.txt`) DO set __lastpagenumber__=%%A
set __lastpagenumber__=%__lastpagenumber__: =%
if exist %__tmpfile__% del %__tmpfile__%
:output
echo The PDF-File: %__pdffilename__% contains %__lastpagenumber__% pages
goto end
:error1
echo no pdf file selected
echo usage: %~n0 PDFFILE
goto end
:error2
echo no pdf file found
echo usage: %~n0 PDFFILE
goto end
:error3
echo.can not find the ghostscript bin file
echo. %__gs__%
echo.please download it from:
echo. http://www.ghostscript.com/download/
echo.and install to "C:\prg\ghostscript"
goto end
:end
exit /b
Ответ 10
Пакет R pdftools, а функция pdf_info()
содержит информацию о количестве страниц в формате pdf.
library(pdftools)
pdf_file <- file.path(R.home("doc"), "NEWS.pdf")
info <- pdf_info(pdf_file)
nbpages <- info[2]
nbpages
$pages
[1] 65