Pobierz liczbę stron w dokumencie PDF
to pytanie jest do odwołania i porównania. Rozwiązaniem jest zaakceptowana odpowiedź poniżej .
Wiele godzin Szukałem szybkiego i łatwego, ale przede wszystkim dokładnego , sposobu na uzyskanie liczby stron w dokumencie PDF. Ponieważ pracuję dla firmy zajmującej się drukowaniem i reprodukcją grafiki, która dużo pracuje z plikami PDF, liczba stron w dokumencie musi być dokładnie znana, zanim zostaną przetworzone. Dokumenty PDF pochodzą od wielu różnych klientów, więc nie są generowane przy użyciu tej samej aplikacji i / lub nie używają tej samej metody kompresji.
Oto kilka odpowiedzi, które znalazłem niewystarczająca lub po prostu nie działa:
Using Imagick (A PHP extension)
Imagick wymaga dużo instalacji, Apache musi się zrestartować, a kiedy w końcu go uruchomiłem, przetwarzanie trwało niesamowicie długo (2-3 minuty na dokument) i zawsze zwracało 1
stronę w każdym dokument (do tej pory nie widziałem roboczej kopii Imagicka), więc go wyrzuciłem. Było to zarówno metodą getNumberImages()
, jak i identifyImage()
.
Using FPDI (A PHP library)
FPDI jest łatwy w użyciu i instalacji (wystarczy rozpakować pliki i wywołać skrypt PHP), ale wiele technik kompresji nie jest wspieranych przez FPDI. Następnie zwraca błąd:
Błąd FPDF: ten dokument (test_1.pdf) prawdopodobnie wykorzystuje technikę kompresji, która nie jest obsługiwana przez darmowy parser dostarczany z FPDI.
Otwieranie strumienia i wyszukiwanie za pomocą wyrażenia regularnego:
Otwiera plik PDF w strumieniu i wyszukuje jakiś łańcuch zawierający liczbę stron lub coś podobnego.
$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+)/
(szuka/Count <number>
) nie działa, ponieważ tylko kilka dokumentów ma parametr/Count
w środku, więc przez większość czasu nic nie zwraca. źródło. -
/\/Page\W*(\d+)/
(szuka/Page<number>
) nie dostaje liczba stron, w większości zawiera inne dane. Źródło. -
/\/N\s+(\d+)/
(szuka/N <number>
) również nie działa, ponieważ dokumenty mogą zawierać wiele wartości/N
; większość, jeśli nie wszystkie, Nie zawiera liczbę stron. źródło.
Więc, co działa niezawodne i dokładne?
8 answers
Prosty program wykonywalny z linii poleceń o nazwie: pdfinfo .
Jest to do pobrania dla Linuksa i Windows. Pobierasz skompresowany plik zawierający kilka małych programów związanych z plikami PDF. Wyciągnij to gdzieś.
Jednym z tych plików jest pdfinfo (lub pdfinfo.exe Dla Windows). Przykład danych zwracanych przez uruchomienie ich na dokumencie 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
Nie widziałem dokumentu PDF, w którym zwrócił fałszywą liczbę stron (jeszcze). Jest to również naprawdę szybki, nawet przy dużych dokumentach 200 + MB czas reakcji wynosi zaledwie kilka sekund lub mniej.
Istnieje łatwy sposób na wyodrębnienie liczby stron z wyjścia, tutaj w 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
Oczywiście to narzędzie wiersza poleceń może być używane w innych językach, które mogą analizować wyjście z zewnętrznego programu, ale używam go w PHP.
Wiem, że nie jest to czysty PHP , ale zewnętrzne programy są sposób lepiej w obsłudze PDF (jak widać w pytaniu).
Mam nadzieję, że to może pomagaj ludziom, ponieważ spędziłem dużo czasu próbując znaleźć rozwiązanie tego problemu i widziałem wiele pytań dotyczących PDF pagecount, w których nie znalazłem odpowiedzi, której szukałem. Dlatego zadałem to pytanie i sam na nie odpowiedziałem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-02 13:23:49
Najprostszym ze wszystkich jest użycie ImageMagick
Oto przykładowy kod
$image = new Imagick();
$image->pingImage('myPdfFile.pdf');
echo $image->getNumberImages();
W przeciwnym razie możesz również użyć PDF
bibliotek, takich jak MPDF
lub TCPDF
dla PHP
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-11 05:31:44
Jeśli masz dostęp do powłoki, najprostszym (ale nie używalnym na 100% plików PDF) podejściem byłoby użycie grep
.
To powinno zwracać tylko liczbę stron:
grep -m 1 -aoP '(?<=\/N )\d+(?=\/)' file.pdf
Przykład: https://regex101.com/r/BrUTKn/1
Opis przełączników:
- Jest to konieczne, ponieważ niektóre pliki mogą mieć więcej niż jedno dopasowanie wzorca regex (volonteer musiał zastąpić to rozszerzeniem rozwiązania regex tylko dla pierwszego dopasowania)
-
-a
jest należy traktować plik binarny jako tekst -
-o
aby pokazać tylko mecz -
-P
aby użyć wyrażenia regularnego Perla
Wyjaśnienie Regex:
- start "delimiter":
(?<=\/N )
lookbehind of/N
(nb. space character not seen here) - rzeczywisty wynik:
\d+
dowolna liczba cyfr - ending "delimiter":
(?=\/)
lookahead of/
Nota bene: jeśli w jakimś przypadku dopasowanie nie zostanie znalezione, można założyć tylko 1 stronę istnieje.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-21 16:06:16
Jeśli nie możesz zainstalować żadnych dodatkowych pakietów, możesz użyć tego prostego jednowiersza:
foundPages=$(strings < $PDF_FILE | sed -n 's|.*Count -\{0,1\}\([0-9]\{1,\}\).*|\1|p' | sort -rn | head -n 1)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-25 05:10:56
Oto funkcja R
, która zgłasza numer strony pliku PDF za pomocą polecenia 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")
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-13 19:41:54
Oto skrypt poleceń systemu Windows wykorzystujący gsscript, który zgłasza numer strony pliku 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-03 00:17:06
Pakiet R pdftools i funkcja pdf_info()
dostarczają informacji o liczbie stron w pliku pdf.
library(pdftools)
pdf_file <- file.path(R.home("doc"), "NEWS.pdf")
info <- pdf_info(pdf_file)
nbpages <- info[2]
nbpages
$pages
[1] 65
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-18 22:03:31
Wygląda na to, że działa to całkiem dobrze, bez potrzeby stosowania specjalnych pakietów lub analizowania wyjścia poleceń.
<?php
$target_pdf = "multi-page-test.pdf";
$cmd = sprintf("identify %s", $target_pdf);
exec($cmd, $output);
$pages = count($output);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-01 21:40:58