获取PDF文档中的页数
这个问题是为了参考和比较。 解决方法是下面接受的答案 。
我花了很多时间search一个快速简单,但大多数是准确的方法来获取PDF文档中的页数。 由于我工作的graphics打印和复制公司,与PDF工作了很多,一个文件中的页面数量必须精确知道之前,他们被处理。 PDF文档来自许多不同的客户端,所以它们不是由相同的应用程序生成的和/或不使用相同的压缩方法。
这里有一些答案我觉得不够或者根本就不行 :
使用Imagick (一个PHP扩展)
Imagick需要大量的安装,apache需要重新启动,当我最终工作时,花了很长时间来处理(每个文档2-3分钟),并且每个文档总是返回1
页(没有看到工作Imagick迄今的副本),所以我把它扔了。 这是与getNumberImages()
和identifyImage()
方法。
使用FPDI (一个PHP库)
FPDI易于使用和安装(只是提取文件和调用PHP脚本), 但许多压缩技术不受FPDI支持。 然后它返回一个错误:
FPDF错误:此文档(test_1.pdf)可能使用FPDI附带的免费parsing器不支持的压缩技术。
打开一个stream并使用正则expression式进行search:
这将打开一个stream中的PDF文件,并search某种types的string,包含pagecount或类似的东西。
$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>
)不起作用,因为只有less数文档具有参数/Count
内部,所以大部分时间不返回任何内容。 资源。 -
/\/Page\W*(\d+)/
(查找/Page<number>
)不会获得页面的数量,大多包含一些其他的数据。 资源。 -
/\/N\s+(\d+)/
(查找/N <number>
)也不起作用,因为文档可以包含多个/N
值; 大部分(如果不是全部的话) 不包含pagecount。 资源。
那么,什么工作可靠和准确?
请参阅下面的答案
一个简单的命令行可执行文件叫做: pdfinfo 。
它可以在Linux和Windows下载 。 您可以下载一个包含几个与PDF相关的程序的压缩文件。 把它解压到某个地方。
其中一个文件是pdfinfo (或Windows的pdfinfo.exe )。 通过在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文档,它返回了一个错误的pagecount(还)。 这也是非常快的,即使是200 + MB的大文件,响应时间只有几秒钟或更less。
有一个简单的方法从输出中提取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
当然,这个命令行工具可以用于其他语言,可以parsing来自外部程序的输出,但我使用它在PHP中。
我知道它不是纯粹的PHP ,但外部程序在PDF处理方面更好(如问题所示)。
我希望这可以帮助人们,因为我花了很多时间试图find解决办法,我看到了很多关于PDF pagecount的问题,我没有find我正在寻找的答案。 这就是为什么我自己提出这个问题并回答的原因。
最简单的就是使用ImageMagick
这里是一个示例代码
$image = new Imagick(); $image->pingImage('myPdfFile.pdf'); echo $image->getNumberImages();
否则,你也可以使用PDF
库,如MPDF
或TCPDF
的PHP
如果你不能安装任何额外的软件包,你可以使用这个简单的一行:
foundPages=$(strings < $PDF_FILE | sed -n 's|.*Count -\{0,1\}\([0-9]\{1,\}\).*|\1|p' | sort -rn | head -n 1)
这是一个R
函数,它使用pdfinfo
命令报告PDF文件的页码。
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") }
这是一个使用gsscript的Windows命令脚本,它报告PDF文件的页码
@echo off echo. rem rem this file: getlastpagenumber.cmd rem version 0.1 from commander 2015-11-03 rem need Ghostscript eg 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
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
这似乎工作得很好,不需要特殊的包或parsing命令输出。
<?php $target_pdf = "multi-page-test.pdf"; $cmd = sprintf("identify %s", $target_pdf); exec($cmd, $output); $pages = count($output);
如果你有权访问shell,最简单的(但不能在100%的PDF上使用)的方法是使用grep
。
这应该只返回页面数量:
grep -m 1 -aoP '(?<=\/N )\d+(?=\/)' file.pdf
例如: https : //regex101.com/r/BrUTKn/1
开关描述:
-
-m 1
是必要的,因为一些文件可以具有多于一个的正则expression式模式匹配(volonteer需要用匹配 – 第一正则expression式解决scheme扩展来replace它) -
-a
需要将二进制文件视为文本 -
-o
只显示比赛 -
-P
使用Perl正则expression式
正则expression式解释:
- 开始“分隔符”:
(?<=\/N )
/N
(后面的空格字符在这里看不到) - 实际结果:
\d+
任意位数 - 以“delimiter”结尾:
(?=\/)
lookahead of/
注意:如果在某些情况下没有find匹配,那么假设只存在1个页面是安全的。