web-dev-qa-db-fra.com

Obtenir le nombre de pages dans un PDF document

_ {Cette question concerne le référencement et la comparaison. La solution est la réponse acceptée ci-dessous .

J'ai passé de nombreuses heures à chercher un moyen rapide et facile, mais surtout le {exact, d'obtenir le nombre de pages d'un document PDF. Étant donné que je travaille pour une entreprise d’impression et de reproduction graphique qui travaille beaucoup avec les PDF, le nombre de pages d’un document doit être connu avec précision avant son traitement. PDF les documents proviennent de nombreux clients différents. Ils ne sont donc pas générés avec la même application et/ou n'utilisent pas la même méthode de compression.

Voici certaines des réponses que j'ai trouvées insuffisant ou tout simplement ne fonctionne pas:

Utilisation de Imagick (une extension PHP)

Imagick nécessite beaucoup d’installation, Apache doit redémarrer, et quand j’ai enfin eu le temps de fonctionner, le traitement a pris un temps incroyable (2 à 3 minutes par document) et il retournait toujours la page 1 dans chaque document copie d’Imagick jusqu’à présent), alors je l’ai jeté. C'était avec les méthodes getNumberImages() et identifyImage().

Utilisation de FPDI (une bibliothèque PHP)

FPDI est facile à utiliser et à installer (il suffit d'extraire des fichiers et d'appeler un script PHP), MAIS de nombreuses techniques de compression ne sont pas prises en charge par FPDI. Il retourne ensuite une erreur:

Erreur FPDF: Ce document (test_1.pdf) utilise probablement une technique de compression qui n’est pas prise en charge par l’analyseur gratuit fourni avec FPDI.

Ouvrir un flux et rechercher avec une expression régulière:

Cela ouvre le fichier PDF dans un flux et recherche un type de chaîne contenant le nombre de pages ou quelque chose de similaire.

$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+)/ (cherche /Count <number>) ne fonctionne pas car seuls quelques documents ont le paramètre /Count à l'intérieur, de sorte que la plupart du temps, ils ne renvoient rien. La source.
  • /\/Page\W*(\d+)/ (cherche /Page<number>) n'obtient pas le nombre de pages, contient la plupart du temps d'autres données. La source.
  • /\/N\s+(\d+)/ (cherche /N <number>) ne fonctionne pas non plus, car les documents peuvent contenir plusieurs valeurs de /N; la plupart sinon la totalité pas contenant le nombre de pages. La source.

Alors, qu'est-ce que le travail est fiable et précis?

Voir la réponse ci-dessous

53
Richard de Wit

Un exécutable simple en ligne de commande appelé: pdfinfo.

Il est téléchargeable pour Linux et Windows . Vous téléchargez un fichier compressé contenant plusieurs petits programmes liés à PDF. Extrait-le quelque part.

Un de ces fichiers est pdfinfo (ou pdfinfo.exe pour Windows). Un exemple de données renvoyées en l’exécutant sur un PDF document:

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

Je n'ai pas vu un PDF document où il a retourné un faux numéro de page (pour le moment). Il est également très rapide, même avec des documents volumineux de plus de 200 Mo. Le temps de réponse est de quelques secondes ou moins.

Il existe un moyen simple d'extraire le nombre de pages de la sortie, ici en 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

Bien sûr, cet outil de ligne de commande peut être utilisé dans d'autres langages pouvant analyser les résultats d'un programme externe, mais je l'utilise en PHP.

Je sais que ce n'est pas pur PHP, mais les programmes externes sont chemin meilleurs en PDF traitement (comme on le voit dans la question).

J'espère que cela pourra aider les gens, car j'ai passé beaucoup de temps à essayer de trouver la solution et j'ai vu beaucoup de questions sur PDF pagecount dans lesquelles je n'ai pas trouvé de réponse. cherchais. C'est pourquoi j'ai posé cette question et y ai répondu moi-même.

77
Richard de Wit

Le plus simple est d'utiliser ImageMagick  

voici un exemple de code

$image = new Imagick();
$image->pingImage('myPdfFile.pdf');
echo $image->getNumberImages();

sinon, vous pouvez également utiliser les bibliothèques PDF telles que MPDF ou TCPDF pour PHP

15
Kuldeep Dangi

Si vous avez accès à Shell, une approche plus simple (mais non utilisable sur 100% des fichiers PDF) consiste à utiliser grep

Cela devrait renvoyer uniquement le nombre de pages:

grep -m 1 -aoP '(?<=\/N )\d+(?=\/)' file.pdf

Exemple: https://regex101.com/r/BrUTKn/1

Description des commutateurs:

  • -m 1 est nécessaire car certains fichiers peuvent avoir plusieurs correspondances de motif de regex (volonteer de le remplacer par une extension de solution correspondant uniquement au premier regex)
  • -a est nécessaire pour traiter le fichier binaire en tant que texte
  • -o pour afficher uniquement la correspondance
  • -P pour utiliser l'expression régulière Perl

Explication regex:

  • démarrage du "délimiteur": (?<=\/N ) lookbehind de /N (nb. espace non visible ici)
  • résultat actuel: \d+ n'importe quel nombre de chiffres
  • se terminant par "délimiteur": (?=\/) lookahead de /

Remarque: si, dans certains cas, aucune correspondance n'est trouvée, il est prudent de supposer qu'une seule page existe.

1
Saran

Puisque vous utilisez les utilitaires de ligne de commande, vous pouvez utiliser cpdf (Microsoft Windows/Linux/Mac OS X). Pour obtenir le nombre de pages dans un PDF:

cpdf.exe -pages "my file.pdf"
1

Vous pouvez utiliser qpdf comme ci-dessous. Si un fichier nom_fichier.pdf comporte 100 pages,

$ qpdf --show-npages file_name.pdf
100
1
SuperNova

Cela semble fonctionner assez bien, sans avoir besoin de paquetages spéciaux ni de sortie de commande d'analyse.

<?php                                                                               

$target_pdf = "multi-page-test.pdf";                                                
$cmd = sprintf("identify %s", $target_pdf);                                         
exec($cmd, $output);                                                                
$pages = count($output);
0
dhildreth

Voici une fonction R qui indique le numéro de page du fichier PDF à l’aide de la commande 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")
}
0
Feiming Chen

si vous ne pouvez installer aucun paquet supplémentaire, vous pouvez utiliser ce simple one-liner:

foundPages=$(strings < $PDF_FILE | sed -n 's|.*Count -\{0,1\}\([0-9]\{1,\}\).*|\1|p' | sort -rn | head -n 1)
0
Muad'Dib

Le package R pdftools et la fonction pdf_info() fournissent des informations sur le nombre de pages d'un fichier PDF.

library(pdftools)
pdf_file <- file.path(R.home("doc"), "NEWS.pdf")
info <- pdf_info(pdf_file)
nbpages <- info[2]
nbpages

$pages
[1] 65
0
emeryville

Voici un script de commande Windows utilisant gsscript indiquant le numéro de page du fichier 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
0
commander