Contar páginas de PDF en JavaScript: más que solo un número

2026-09-28 08:34:12 Allen Yang
AI Summarize:
ChatGPT
ChatGPT ✓
Claude ✓
Grok ✓
Perplexity ✓
Quick
Quick
Concise overview
Highlights
Key takeaways
Detailed
Structured explanation
Brief
One sentence summary
Summarize |

The result is written to a text file that records the document's total page count

Un solo número entero —el número total de páginas de un PDF— está detrás de una sorprendente cantidad de decisiones del mundo real: límites de carga, estimación de papel para impresión, operaciones de división, barras de progreso. La mayoría de las bibliotecas de renderización de PDF solo dibujan páginas y no exponen un recuento sencillo, y enviar el archivo a un backend solo para leer un recuento de páginas añade latencia y problemas de privacidad.

Spire.PDF for JavaScript carga y analiza documentos PDF directamente en el navegador mediante WebAssembly, por lo que el archivo nunca sale del cliente. El recuento de páginas está disponible como una única propiedad: sin bucles, sin idas y vueltas al servidor, sin soluciones alternativas de renderización. Este artículo explica cómo obtener ese recuento y tres aspectos prácticos: distinguir el número de páginas físico de las etiquetas de visualización, manejar archivos protegidos con contraseña y evitar errores de desfase (off-by-one) al iterar sobre las páginas.

Para obtener información sobre la instalación y la configuración del proyecto, consulte Integrar Spire.PDF for JavaScript en un proyecto de React. Los ejemplos a continuación asumen que Spire.PDF está instalado y que el módulo WebAssembly se ha inicializado.


Obtener el número de páginas de un documento PDF

Una vez que un objeto PdfDocument ha cargado un archivo, su propiedad Pages expone la colección de páginas, y la propiedad Count de esa colección devuelve el número total de páginas. No es necesario iterar por las páginas individualmente: el recuento está disponible inmediatamente después de la carga.

El siguiente componente de React demuestra el flujo de trabajo completo: obtener el PDF en el sistema de archivos virtual, crear un PdfDocument, cargar el archivo, leer Pages.Count y escribir el resultado en un archivo de texto descargable.

function App() {
  const getPageCount = async () => {
    // Get the Spire.PDF WASM module
    const pdfModule = window.wasmModule?.spirepdf;

    // Check whether the module is ready
    if (!pdfModule) {
      alert('Spire.PDF is not ready yet');
      return;
    }

    // Load the PDF file to be counted into the VFS
    const inputFileName = 'Multipage_Document.pdf';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);

    // Create a PdfDocument object and load the PDF document
    const doc = new pdfModule.PdfDocument();
    doc.LoadFromFile(inputFileName);

    // Pages is the document's page collection; Count is the total page count
    const pageCount = doc.Pages.Count;

    // Write the result to the VFS
    const outputFileName = 'PageCountResult.txt';
    const report = `Document: ${inputFileName}\r\nTotal pages: ${pageCount}`;
    window.dotnetRuntime.Module.FS.writeFile(outputFileName, report);
    doc.Close();

    // Read the generated file from the VFS and trigger the download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Get PDF Page Count</h1>
      <button onClick={getPageCount}>
        Count Pages
      </button>
    </div>
  );
}

export default App;

El resultado se escribe en un archivo de texto que registra el número total de páginas del documento:

The result is written to a text file that records the document's total page count

En una aplicación de producción, normalmente usaría el valor de pageCount directamente en lugar de escribirlo en un archivo; por ejemplo, para validar una carga, establecer un límite de bucle o mostrar metadatos en la interfaz de usuario. El enfoque de salida a archivo que se muestra aquí es útil para pruebas y demostraciones.


Número de páginas físico vs. etiquetas de página

Esta es una situación que pilla a los desarrolladores desprevenidos: usted lee Pages.Count y obtiene 12, pero el lector de PDF en la pantalla del usuario muestra la última página como "página 8". ¿Qué número es correcto?

Ambos lo son: miden cosas diferentes. Pages.Count devuelve el número de páginas físicas del documento, sin más. Sin embargo, el número que muestra un lector proviene de las etiquetas de página (la entrada /PageLabels en la especificación PDF). Las etiquetas de página son una capa de presentación que los editores utilizan para controlar cómo aparecen los números de página ante el lector. Un editor de libros podría excluir la portada de la numeración, usar números romanos (i, ii, iii) para los preliminares y reiniciar el cuerpo en 1. Después de todo eso, la quinta página física podría mostrarse como iii o 1, según cómo estén configuradas las etiquetas.

Esta distinción importa cuando su aplicación necesita mostrar a los usuarios un número de página que coincida con lo que ven en su lector. Si muestra Pages.Count como la "página actual", no coincidirá con la numeración del lector siempre que haya etiquetas de página en juego.

Cuando necesite la etiqueta mostrada en lugar del índice físico, lea la propiedad PageLabel del objeto de página individual:

// What label the 5th physical page displays in a reader
const page = doc.Pages.get_Item(4);
console.log(page.PageLabel);

Tenga en cuenta que el índice empieza en cero: get_Item(4) recupera la quinta página física. Cuando el documento no tiene etiquetas de página configuradas, PageLabel devuelve una cadena vacía. En ese caso habitual, el número mostrado coincide con el orden físico de las páginas, por lo que Count es el valor que desea.

Una forma práctica de manejar ambos escenarios es comprobar primero PageLabel y recurrir al índice físico cuando esté vacío. Esto proporciona a su aplicación un número de página que siempre coincide con lo que ve el usuario, independientemente de si el documento utiliza etiquetas personalizadas.


Contar páginas en un PDF cifrado

Muchos PDF en entornos empresariales están protegidos por una contraseña de apertura, una medida de seguridad que impide leer el documento sin la credencial correcta. Si intenta cargar un archivo así con una llamada simple a LoadFromFile, el entorno de ejecución WASM lanza un error antes de que se llegue a Pages.Count:

No se puede abrir un documento cifrado. La contraseña no es válida.

Esto ocurre en el momento de la carga, no en el punto en el que se lee el recuento de páginas. El contenido del documento, incluida su estructura de páginas, está cifrado, por lo que la biblioteca no puede analizarlo sin la contraseña. No hay forma de contar páginas sin desbloquear primero el documento.

La solución es sencilla: pase la contraseña de apertura como segundo argumento a LoadFromFile. Una vez desbloqueado el documento, el recuento de páginas está disponible igual que con un archivo sin cifrar:

// The second argument is the open password
doc.LoadFromFile(inputFileName, 'spire123');
const pageCount = doc.Pages.Count;

En una aplicación real, normalmente recopilaría la contraseña del usuario a través de un campo de formulario y la pasaría dinámicamente en lugar de codificarla de forma fija. Si el usuario introduce una contraseña incorrecta, se lanza el mismo error, por lo que envolver la llamada a LoadFromFile en un bloque try/catch y mostrar un mensaje amigable de "contraseña incorrecta" es una buena práctica.

Hay algo más que vale la pena señalar: esta contraseña es la contraseña de apertura (también llamada contraseña de usuario), que controla quién puede ver el documento. Un PDF también puede tener una contraseña de permisos (contraseña de propietario) que restringe la edición, la impresión o la copia sin bloquear la visualización. A efectos de contar páginas, solo es relevante la contraseña de apertura: una vez abierto el documento, Pages.Count funciona independientemente de las restricciones de permisos.


Usar el número de páginas como límite de bucle

Una vez que tiene el número de páginas, un siguiente paso natural es recorrer cada página en un bucle: para extraer texto, generar miniaturas, dividir el documento o aplicar alguna transformación. Aquí es donde aparece un error sutil pero común: usar Count como límite superior inclusivo.

La colección Pages está indexada desde cero, lo que significa que los índices válidos van de 0 a Count - 1. Si la condición del bucle se escribe con <= en lugar de <, la iteración final intenta acceder a la página en el índice Count, que no existe. El entorno de ejecución WASM envuelve la excepción subyacente ArgumentOutOfRangeException de .NET como un Error de JavaScript con un mensaje como:

ArgumentOutOfRange_IndexMustBeLess Arg_ParamName_Name, index

Como la propiedad name del error es solo el Error genérico, no puede distinguirlo solo por el nombre: tiene que coincidir con la cadena del mensaje si desea manejarlo específicamente.

El bucle correcto usa <, de modo que el último índice al que se accede es Count - 1:

// The upper bound is Count - 1, so use < rather than <=
for (let i = 0; i < doc.Pages.Count; i++) {
  const page = doc.Pages.get_Item(i);
}

Este patrón de error por desfase (off-by-one) es una de las fuentes más frecuentes de errores en tiempo de ejecución al trabajar con colecciones de páginas. Es fácil pasarlo por alto en las pruebas si sus documentos de ejemplo tienen solo una o dos páginas: el error solo aparece en la iteración final, por lo que un documento de una sola página no lo activará en absoluto. Pruebe siempre la lógica de los bucles con un documento que tenga al menos tres páginas para asegurarse de que la condición de límite sea correcta.


Vea también