JavaScript로 PDF 페이지 수 세기: 단순한 숫자 그 이상

PDF의 총 페이지 수라는 단일 정수는 업로드 제한, 인쇄용 용지 추산, 분할 작업, 진행률 표시줄 등 현실 세계의 놀라울 정도로 많은 결정 뒤에 자리 잡고 있습니다. 대부분의 PDF 렌더링 라이브러리는 페이지만 그릴 뿐 간단한 페이지 수를 노출하지 않으며, 단지 페이지 수를 읽기 위해 파일을 백엔드로 보내는 것은 지연 시간과 개인정보 보호 문제를 야기합니다.
JavaScript용 Spire.PDF는 WebAssembly를 통해 브라우저에서 직접 PDF 문서를 로드하고 구문 분석하므로 파일이 클라이언트를 떠나지 않습니다. 페이지 수는 단일 속성으로 제공됩니다. 루프도, 서버 왕복도, 렌더링 우회도 필요 없습니다. 이 문서에서는 해당 페이지 수를 가져오는 방법과 세 가지 실용적인 고려 사항을 살펴봅니다: 실제 페이지 수와 표시 레이블 구분하기, 암호로 보호된 파일 처리하기, 페이지를 반복할 때 오프바이원 오류 피하기.
설치 및 프로젝트 설정은 React 프로젝트에 JavaScript용 Spire.PDF 통합하기를 참조하세요. 아래 예제는 Spire.PDF가 설치되어 있고 WebAssembly 모듈이 초기화되었다고 가정합니다.
PDF 문서의 페이지 수 가져오기
PdfDocument 개체가 파일을 로드하면 Pages 속성이 페이지 컬렉션을 노출하고, 해당 컬렉션의 Count 속성이 총 페이지 수를 반환합니다. 페이지를 개별적으로 반복할 필요가 없으며, 로드 직후 페이지 수를 사용할 수 있습니다.
다음 React 컴포넌트는 전체 워크플로를 보여줍니다: PDF를 가상 파일 시스템으로 가져오고, PdfDocument를 만들고, 파일을 로드하고, Pages.Count를 읽고, 결과를 다운로드 가능한 텍스트 파일에 작성합니다.
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;
결과는 문서의 총 페이지 수를 기록하는 텍스트 파일에 작성됩니다:

프로덕션 애플리케이션에서는 일반적으로 pageCount 값을 파일에 작성하기보다 직접 사용합니다. 예를 들어 업로드를 검증하거나, 루프 경계를 설정하거나, UI에 메타데이터를 표시할 때 사용합니다. 여기서 보여 주는 파일 출력 방식은 테스트와 데모에 유용합니다.
실제 페이지 수와 페이지 레이블
개발자를 당황하게 만드는 상황이 있습니다. Pages.Count를 읽었는데 12가 나오지만, 사용자 화면의 PDF 리더는 마지막 페이지를 "8페이지"로 표시합니다. 어느 숫자가 맞을까요?
둘 다 맞습니다. 서로 다른 것을 측정하기 때문입니다. Pages.Count는 문서의 실제 페이지 수를 그대로 반환합니다. 반면 리더에 표시되는 숫자는 페이지 레이블(PDF 사양의 /PageLabels 항목)에서 나옵니다. 페이지 레이블은 게시자가 독자에게 페이지 번호가 표시되는 방식을 제어하기 위해 사용하는 표현 계층입니다. 책 출판사는 표지를 번호 매기기에서 제외하고, 앞부분에 로마 숫자(i, ii, iii)를 사용하고, 본문을 1부터 다시 시작할 수 있습니다. 그렇게 하면 다섯 번째 실제 페이지는 레이블 구성 방식에 따라 iii 또는 1로 표시될 수 있습니다.
이 구분은 애플리케이션이 사용자에게 리더에서 보는 것과 일치하는 페이지 번호를 표시해야 할 때 중요합니다. Pages.Count를 "현재 페이지"로 표시하면 페이지 레이블이 사용되는 경우 리더의 번호 매기기와 일치하지 않습니다.
실제 인덱스가 아니라 표시되는 레이블이 필요할 때는 개별 페이지 개체의 PageLabel 속성을 읽습니다:
// What label the 5th physical page displays in a reader
const page = doc.Pages.get_Item(4);
console.log(page.PageLabel);
0부터 시작하는 인덱스에 유의하세요. get_Item(4)는 다섯 번째 실제 페이지를 가져옵니다. 문서에 구성된 페이지 레이블이 없으면 PageLabel은 빈 문자열을 반환합니다. 이러한 일반적인 경우 표시되는 숫자가 실제 페이지 순서와 일치하므로 Count가 원하는 값입니다.
두 시나리오를 모두 처리하는 실용적인 방법은 먼저 PageLabel을 확인하고 비어 있으면 실제 인덱스로 대체하는 것입니다. 이렇게 하면 문서가 사용자 지정 레이블을 사용하든 아니든 애플리케이션이 항상 사용자가 보는 것과 일치하는 페이지 번호를 제공할 수 있습니다.
암호화된 PDF의 페이지 수 세기
비즈니스 환경의 많은 PDF는 열기 암호로 보호됩니다. 이는 올바른 자격 증명 없이는 문서를 읽을 수 없게 하는 보안 조치입니다. 이러한 파일을 일반 LoadFromFile 호출로 로드하려고 하면 WASM 런타임이 Pages.Count에 도달하기도 전에 오류를 throw합니다:
암호화된 문서를 열 수 없습니다. 암호가 올바르지 않습니다.
이 문제는 페이지 수를 읽는 시점이 아니라 로드 시점에 발생합니다. 문서의 내용(페이지 구조 포함)이 암호화되어 있으므로 라이브러리는 암호 없이 구문 분석할 수 없습니다. 먼저 문서의 잠금을 해제하지 않고는 페이지 수를 셀 방법이 없습니다.
해결 방법은 간단합니다. 열기 암호를 LoadFromFile의 두 번째 인수로 전달하세요. 문서의 잠금이 해제되면 암호화되지 않은 파일과 마찬가지로 페이지 수를 사용할 수 있습니다:
// The second argument is the open password
doc.LoadFromFile(inputFileName, 'spire123');
const pageCount = doc.Pages.Count;
실제 애플리케이션에서는 일반적으로 양식 필드를 통해 사용자로부터 암호를 수집하고 하드코딩하는 대신 동적으로 전달합니다. 사용자가 잘못된 암호를 입력하면 동일한 오류가 throw되므로 LoadFromFile 호출을 try/catch 블록으로 감싸고 친숙한 "잘못된 암호" 메시지를 표시하는 것이 좋습니다.
한 가지 더 주목할 점은 이 암호가 열기 암호(사용자 암호라고도 함)라는 것입니다. 이는 누가 문서를 볼 수 있는지 제어합니다. PDF에는 보기 차단 없이 편집, 인쇄 또는 복사를 제한하는 권한 암호(소유자 암호)가 있을 수도 있습니다. 페이지 수를 세는 목적에서는 열기 암호만 관련이 있습니다. 문서가 열리면 Pages.Count는 권한 제한과 관계없이 작동합니다.
페이지 수를 루프 경계로 사용하기
페이지 수를 구한 후 자연스러운 다음 단계는 모든 페이지를 반복하는 것입니다. 텍스트 추출, 썸네일 렌더링, 문서 분할 또는 일부 변환 적용 등이 있습니다. 여기에서 미묘하지만 흔한 버그가 나타납니다. Count를 포함 상한으로 사용하는 것입니다.
Pages 컬렉션은 0부터 시작하는 인덱스를 사용하므로 유효한 인덱스는 0부터 Count - 1까지입니다. 루프 조건을 < 대신 <=로 작성하면 마지막 반복에서 존재하지 않는 인덱스 Count의 페이지에 접근하려고 합니다. WASM 런타임은 기본 .NET ArgumentOutOfRangeException을 다음과 같은 메시지의 JavaScript Error로 래핑합니다:
ArgumentOutOfRange_IndexMustBeLess Arg_ParamName_Name, index
오류의 name 속성이 일반 Error일 뿐이므로 이름만으로 구분할 수 없습니다. 특별히 처리하려면 메시지 문자열을 일치시켜야 합니다.
올바른 루프는 <를 사용하므로 마지막으로 접근하는 인덱스는 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);
}
이 오프바이원 패턴은 페이지 컬렉션으로 작업할 때 가장 흔한 런타임 오류 원인 중 하나입니다. 샘플 문서가 우연히 한두 페이지뿐이라면 테스트에서 놓치기 쉽습니다. 오류는 마지막 반복에서만 나타나므로 한 페이지 문서에서는 전혀 발생하지 않습니다. 경계 조건이 올바른지 확인하려면 항상 최소 세 페이지가 있는 문서로 루프 로직을 테스트하세요.
참고 항목
- React 프로젝트에 JavaScript용 Spire.PDF 통합하기 — Spire.PDF 설치 및 React 앱에서 WebAssembly 모듈 초기화를 위한 설정 가이드입니다.
- JavaScript용 Spire.PDF 제품 페이지 — 기능, 지원되는 작업 및 브라우저 기반 PDF 처리 기능 개요.
- npm의 spire.pdf — npm을 통해 라이브러리를 설치하기 위한 패키지 페이지입니다.
Contare le pagine di un PDF in JavaScript: più di un semplice numero

Un singolo numero intero — il numero totale di pagine di un PDF — è alla base di un numero sorprendente di decisioni concrete: limiti di caricamento, stima della carta per la stampa, operazioni di suddivisione, barre di avanzamento. La maggior parte delle librerie di rendering PDF si limita a disegnare le pagine e non espone un semplice conteggio, e inviare il file a un backend solo per leggere il numero di pagine comporta latenza e problemi di privacy.
Spire.PDF for JavaScript carica e analizza i documenti PDF direttamente nel browser tramite WebAssembly, così il file non lascia mai il client. Il numero di pagine è disponibile come singola proprietà — nessun ciclo, nessun round-trip verso il server, nessuna soluzione alternativa basata sul rendering. Questo articolo illustra come recuperare tale conteggio e tre aspetti pratici: distinguere il numero di pagine fisiche dalle etichette visualizzate, gestire i file protetti da password ed evitare errori di off-by-one durante l'iterazione sulle pagine.
Per l'installazione e la configurazione del progetto, consulta Integrare Spire.PDF for JavaScript in un progetto React. Gli esempi seguenti presuppongono che Spire.PDF sia installato e che il modulo WebAssembly sia stato inizializzato.
Ottenere il numero di pagine di un documento PDF
Dopo che un oggetto PdfDocument ha caricato un file, la sua proprietà Pages espone la raccolta delle pagine e la proprietà Count di tale raccolta restituisce il numero totale di pagine. Non è necessario scorrere le pagine una per una — il conteggio è disponibile subito dopo il caricamento.
Il seguente componente React mostra l'intero flusso di lavoro: recupera il PDF nel file system virtuale, crea un PdfDocument, carica il file, legge Pages.Count e scrive il risultato in un file di testo scaricabile.
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;
Il risultato viene scritto in un file di testo che registra il numero totale di pagine del documento:

In un'applicazione di produzione, in genere useresti direttamente il valore pageCount invece di scriverlo in un file — ad esempio per convalidare un caricamento, impostare il limite di un ciclo o mostrare metadati nell'interfaccia utente. L'approccio con output su file mostrato qui è utile per i test e per scopi dimostrativi.
Numero di pagine fisiche vs etichette di pagina
Ecco una situazione che coglie di sorpresa gli sviluppatori: leggi Pages.Count e ottieni 12, ma il lettore PDF sullo schermo dell'utente mostra l'ultima pagina come "pagina 8". Quale numero è corretto?
Lo sono entrambi — misurano cose diverse. Pages.Count restituisce il numero di pagine fisiche del documento, in modo semplice e diretto. Il numero visualizzato da un lettore, invece, deriva dalle etichette di pagina (la voce /PageLabels nella specifica PDF). Le etichette di pagina sono un livello di presentazione che gli editori usano per controllare come i numeri di pagina appaiono al lettore. Un editore di libri potrebbe escludere la copertina dalla numerazione, usare numeri romani (i, ii, iii) per le pagine introduttive e ricominciare il corpo da 1. Dopo tutto questo, la quinta pagina fisica potrebbe apparire come iii o 1 a seconda di come sono configurate le etichette.
Questa distinzione è importante quando l'applicazione deve mostrare agli utenti un numero di pagina che corrisponda a quello che vedono nel loro lettore. Se visualizzi Pages.Count come "pagina corrente", non coinciderà con la numerazione del lettore ogni volta che sono in gioco le etichette di pagina.
Quando ti serve l'etichetta visualizzata anziché l'indice fisico, leggi la proprietà PageLabel sul singolo oggetto pagina:
// What label the 5th physical page displays in a reader
const page = doc.Pages.get_Item(4);
console.log(page.PageLabel);
Nota l'indice a base zero: get_Item(4) recupera la quinta pagina fisica. Quando il documento non ha etichette di pagina configurate, PageLabel restituisce una stringa vuota. In questo caso comune, il numero visualizzato corrisponde all'ordine fisico delle pagine, quindi Count è il valore che ti serve.
Un modo pratico per gestire entrambi gli scenari è controllare prima PageLabel e ricorrere all'indice fisico quando è vuoto. In questo modo la tua applicazione ottiene un numero di pagina che corrisponde sempre a ciò che vede l'utente, indipendentemente dal fatto che il documento utilizzi etichette personalizzate.
Contare le pagine in un PDF crittografato
Molti PDF negli ambienti aziendali sono protetti da una password di apertura — una misura di sicurezza che impedisce la lettura del documento senza le credenziali corrette. Se provi a caricare un file di questo tipo con una semplice chiamata LoadFromFile, il runtime WASM genera un errore prima ancora di arrivare a Pages.Count:
Impossibile aprire un documento crittografato. La password non è valida.
Ciò accade al momento del caricamento, non nel punto in cui leggi il numero di pagine. Il contenuto del documento — inclusa la sua struttura di pagine — è crittografato, quindi la libreria non può analizzarlo senza la password. Non c'è modo di contare le pagine senza prima sbloccare il documento.
La soluzione è semplice: passa la password di apertura come secondo argomento a LoadFromFile. Una volta sbloccato il documento, il numero di pagine è disponibile esattamente come per un file non crittografato:
// The second argument is the open password
doc.LoadFromFile(inputFileName, 'spire123');
const pageCount = doc.Pages.Count;
In un'applicazione reale, in genere raccoglieresti la password dall'utente tramite un campo di un modulo e la passeresti dinamicamente invece di inserirla nel codice. Se l'utente inserisce la password sbagliata, viene generato lo stesso errore — quindi racchiudere la chiamata LoadFromFile in un blocco try/catch e mostrare un messaggio amichevole di "password errata" è una buona pratica.
C'è un'altra cosa da notare: questa password è la password di apertura (chiamata anche password utente), che controlla chi può visualizzare il documento. Un PDF può avere anche una password di autorizzazione (password proprietario) che limita la modifica, la stampa o la copia senza bloccare la visualizzazione. Ai fini del conteggio delle pagine, è rilevante solo la password di apertura — una volta aperto il documento, Pages.Count funziona indipendentemente dalle restrizioni di autorizzazione.
Usare il numero di pagine come limite di un ciclo
Una volta ottenuto il numero di pagine, un passo successivo naturale è scorrere ogni pagina — per estrarre testo, generare anteprime, dividere il documento o applicare qualche trasformazione. È qui che compare un bug sottile ma comune: usare Count come limite superiore inclusivo.
La raccolta Pages è a base zero, il che significa che gli indici validi vanno da 0 a Count - 1. Se la condizione del ciclo è scritta con <= invece di <, l'iterazione finale tenta di accedere alla pagina con indice Count, che non esiste. Il runtime WASM incapsula l'eccezione .NET sottostante ArgumentOutOfRangeException come Error JavaScript con un messaggio simile a:
ArgumentOutOfRange_IndexMustBeLess Arg_ParamName_Name, index
Poiché la proprietà name dell'errore è solo il generico Error, non puoi distinguerlo dal solo nome — devi confrontare la stringa del messaggio se vuoi gestirlo in modo specifico.
Il ciclo corretto usa < in modo che l'ultimo indice a cui si accede sia 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);
}
Questo schema di off-by-one è una delle fonti più frequenti di errori di runtime quando si lavora con raccolte di pagine. È facile non accorgersene durante i test se i documenti di esempio hanno solo una o due pagine — l'errore emerge solo all'iterazione finale, quindi un documento di una sola pagina non lo attiverà affatto. Testa sempre la logica del ciclo con un documento che abbia almeno tre pagine per assicurarti che la condizione al contorno sia corretta.
Vedi anche
- Integrare Spire.PDF for JavaScript in un progetto React — Guida alla configurazione per installare Spire.PDF e inizializzare il modulo WebAssembly in un'app React.
- Pagina del prodotto Spire.PDF for JavaScript — Panoramica delle funzionalità, delle operazioni supportate e delle capacità di elaborazione PDF basata su browser.
- spire.pdf su npm — Pagina del pacchetto per installare la libreria tramite npm.
Compter les pages d'un PDF en JavaScript : plus qu'un simple nombre

Un simple entier — le nombre total de pages d'un PDF — se cache derrière un nombre surprenant de décisions concrètes : limites de téléversement, estimation du papier pour l'impression, opérations de fractionnement, barres de progression. La plupart des bibliothèques de rendu PDF se contentent de dessiner les pages et n'exposent pas de simple compteur, et envoyer le fichier à un backend juste pour lire un nombre de pages ajoute de la latence et soulève des problèmes de confidentialité.
Spire.PDF for JavaScript charge et analyse les documents PDF directement dans le navigateur via WebAssembly, ainsi le fichier ne quitte jamais le client. Le nombre de pages est disponible sous la forme d'une seule propriété — sans boucles, sans allers-retours vers le serveur, sans contournements de rendu. Cet article explique comment récupérer ce nombre et aborde trois préoccupations pratiques : distinguer les nombres de pages physiques des étiquettes affichées, gérer les fichiers protégés par mot de passe, et éviter les erreurs de décalage d'un lorsque l'on parcourt les pages.
Pour l'installation et la configuration du projet, consultez Intégrer Spire.PDF for JavaScript dans un projet React. Les exemples ci-dessous supposent que Spire.PDF est installé et que le module WebAssembly a été initialisé.
Obtenir le nombre de pages d'un document PDF
Une fois qu'un objet PdfDocument a chargé un fichier, sa propriété Pages expose la collection de pages, et la propriété Count de cette collection renvoie le nombre total de pages. Il n'est pas nécessaire de parcourir les pages une à une — le nombre est disponible immédiatement après le chargement.
Le composant React suivant illustre le flux de travail complet : récupérer le PDF dans le système de fichiers virtuel, créer un PdfDocument, charger le fichier, lire Pages.Count, et écrire le résultat dans un fichier texte téléchargeable.
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;
Le résultat est écrit dans un fichier texte qui enregistre le nombre total de pages du document :

Dans une application de production, vous utiliseriez généralement la valeur pageCount directement plutôt que de l'écrire dans un fichier — par exemple, pour valider un téléversement, définir une limite de boucle, ou afficher des métadonnées dans l'interface. L'approche de sortie vers un fichier présentée ici est utile pour les tests et la démonstration.
Nombre de pages physiques vs étiquettes de page
Voici une situation qui prend les développeurs au dépourvu : vous lisez Pages.Count et obtenez 12, mais le lecteur PDF à l'écran de l'utilisateur affiche la dernière page comme « page 8 ». Quel nombre est correct ?
Les deux le sont — ils mesurent des choses différentes. Pages.Count renvoie le nombre de pages physiques du document, tout simplement. Le nombre affiché par un lecteur, en revanche, provient des étiquettes de page (l'entrée /PageLabels dans la spécification PDF). Les étiquettes de page constituent une couche de présentation que les éditeurs utilisent pour contrôler la façon dont les numéros de page apparaissent au lecteur. Un éditeur de livre peut exclure la couverture de la numérotation, utiliser des chiffres romains (i, ii, iii) pour les pages liminaires, et redémarrer le corps à 1. Après tout cela, la cinquième page physique pourrait s'afficher comme iii ou 1 selon la configuration des étiquettes.
Cette distinction importe lorsque votre application doit afficher à l'utilisateur un numéro de page correspondant à ce qu'il voit dans son lecteur. Si vous affichez Pages.Count comme « page actuelle », cela ne correspondra pas à la numérotation du lecteur chaque fois que des étiquettes de page sont en jeu.
Lorsque vous avez besoin de l'étiquette affichée plutôt que de l'index physique, lisez la propriété PageLabel sur l'objet de page individuel :
// What label the 5th physical page displays in a reader
const page = doc.Pages.get_Item(4);
console.log(page.PageLabel);
Notez que l'index est basé sur zéro : get_Item(4) récupère la cinquième page physique. Lorsque le document n'a pas d'étiquettes de page configurées, PageLabel renvoie une chaîne vide. Dans ce cas courant, le numéro affiché correspond à l'ordre des pages physiques, donc Count est la valeur que vous voulez.
Une manière pratique de gérer les deux scénarios consiste à vérifier d'abord PageLabel et à revenir à l'index physique lorsqu'il est vide. Cela donne à votre application un numéro de page qui correspond toujours à ce que l'utilisateur voit, que le document utilise ou non des étiquettes personnalisées.
Compter les pages d'un PDF chiffré
De nombreux PDF dans les environnements professionnels sont protégés par un mot de passe d'ouverture — une mesure de sécurité qui empêche la lecture du document sans les identifiants corrects. Si vous essayez de charger un tel fichier avec un simple appel LoadFromFile, le moteur d'exécution WASM lève une erreur avant même que Pages.Count ne soit atteint :
Impossible d'ouvrir un document chiffré. Le mot de passe est invalide.
Cela se produit au moment du chargement, et non au moment où vous lisez le nombre de pages. Le contenu du document — y compris sa structure de pages — est chiffré, donc la bibliothèque ne peut pas l'analyser sans le mot de passe. Il n'est pas possible de compter les pages sans d'abord déverrouiller le document.
La solution est simple : transmettez le mot de passe d'ouverture comme deuxième argument à LoadFromFile. Une fois le document déverrouillé, le nombre de pages est disponible exactement comme pour un fichier non chiffré :
// The second argument is the open password
doc.LoadFromFile(inputFileName, 'spire123');
const pageCount = doc.Pages.Count;
Dans une application réelle, vous collecteriez généralement le mot de passe auprès de l'utilisateur via un champ de formulaire et le transmetteriez dynamiquement plutôt que de le coder en dur. Si l'utilisateur saisit un mot de passe erroné, la même erreur est levée — il est donc recommandé d'envelopper l'appel LoadFromFile dans un bloc try/catch et d'afficher un message convivial « mot de passe incorrect ».
Une autre précision à noter : ce mot de passe est le mot de passe d'ouverture (aussi appelé mot de passe utilisateur), qui contrôle qui peut consulter le document. Un PDF peut également avoir un mot de passe de permissions (mot de passe propriétaire) qui restreint la modification, l'impression ou la copie sans bloquer la consultation. Pour ce qui est de compter les pages, seul le mot de passe d'ouverture est pertinent — une fois le document ouvert, Pages.Count fonctionne indépendamment des restrictions de permissions.
Utiliser le nombre de pages comme limite de boucle
Une fois que vous avez le nombre de pages, une étape naturelle consiste à parcourir chaque page — pour extraire du texte, générer des miniatures, fractionner le document, ou appliquer une transformation. C'est là qu'apparaît un bug subtil mais courant : utiliser Count comme borne supérieure inclusive.
La collection Pages est basée sur zéro, ce qui signifie que les indices valides vont de 0 à Count - 1. Si la condition de boucle est écrite avec <= au lieu de <, l'itération finale tente d'accéder à la page à l'index Count, qui n'existe pas. Le moteur d'exécution WASM encapsule l'ArgumentOutOfRangeException .NET sous-jacente dans une Error JavaScript avec un message du type :
ArgumentOutOfRange_IndexMustBeLess Arg_ParamName_Name, index
Comme la propriété name de l'erreur est simplement l'Error générique, vous ne pouvez pas la distinguer par son nom seul — vous devez faire correspondre la chaîne du message si vous voulez la gérer spécifiquement.
La boucle correcte utilise <, de sorte que le dernier indice accédé soit 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);
}
Ce schéma de décalage d'un est l'une des sources les plus fréquentes d'erreurs d'exécution lorsqu'on travaille avec des collections de pages. Il est facile à manquer lors des tests si vos documents d'exemple ne comportent qu'une ou deux pages — l'erreur ne se manifeste qu'à l'itération finale, donc un document d'une seule page ne la déclenchera pas du tout. Testez toujours la logique de boucle avec un document comportant au moins trois pages pour vous assurer que la condition de limite est correcte.
Voir aussi
- Intégrer Spire.PDF for JavaScript dans un projet React — Guide de configuration pour installer Spire.PDF et initialiser le module WebAssembly dans une application React.
- Page produit Spire.PDF for JavaScript — Aperçu des fonctionnalités, des opérations prises en charge et des capacités de traitement PDF dans le navigateur.
- spire.pdf sur npm — Page du paquet pour installer la bibliothèque via npm.
Contar páginas de PDF en JavaScript: más que solo un número

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:

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
- Integrar Spire.PDF for JavaScript en un proyecto de React: guía de configuración para instalar Spire.PDF e inicializar el módulo WebAssembly en una aplicación de React.
- Página del producto Spire.PDF for JavaScript: descripción general de las características, las operaciones compatibles y las capacidades de procesamiento de PDF basado en el navegador.
- spire.pdf en npm: página del paquete para instalar la biblioteca mediante npm.
PDF-Seiten in JavaScript zählen: Mehr als nur eine Zahl

Eine einzige Ganzzahl – die Gesamtzahl der Seiten in einer PDF – steckt hinter einer überraschend großen Zahl realer Entscheidungen: Upload-Limits, Papierschätzung für den Druck, Split-Vorgänge, Fortschrittsbalken. Die meisten PDF-Rendering-Bibliotheken zeichnen nur Seiten und stellen keine einfache Zählung bereit, und das Senden der Datei an ein Backend, nur um eine Seitenzahl auszulesen, verursacht Latenz und Datenschutzbedenken.
Spire.PDF für JavaScript lädt und parst PDF-Dokumente direkt im Browser über WebAssembly, sodass die Datei den Client nie verlässt. Die Seitenzahl ist als einzelne Eigenschaft verfügbar – keine Schleifen, keine Server-Roundtrips, keine Rendering-Workarounds. Dieser Artikel beschreibt, wie Sie diese Anzahl abrufen, und drei praktische Aspekte: physische Seitenzahlen von Anzeige-Beschriftungen zu unterscheiden, passwortgeschützte Dateien zu behandeln und Off-by-one-Fehler beim Iterieren über Seiten zu vermeiden.
Informationen zur Installation und Projekteinrichtung finden Sie unter Spire.PDF für JavaScript in ein React-Projekt integrieren. Die folgenden Beispiele gehen davon aus, dass Spire.PDF installiert und das WebAssembly-Modul initialisiert wurde.
Die Seitenzahl eines PDF-Dokuments abrufen
Sobald ein PdfDocument-Objekt eine Datei geladen hat, macht seine Eigenschaft Pages die Seitensammlung verfügbar, und die Eigenschaft Count dieser Sammlung gibt die Gesamtzahl der Seiten zurück. Es ist nicht nötig, die Seiten einzeln zu durchlaufen – die Anzahl ist unmittelbar nach dem Laden verfügbar.
Die folgende React-Komponente demonstriert den vollständigen Ablauf: die PDF in das virtuelle Dateisystem holen, ein PdfDocument erstellen, die Datei laden, Pages.Count auslesen und das Ergebnis in eine herunterladbare Textdatei schreiben.
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;
Das Ergebnis wird in eine Textdatei geschrieben, die die Gesamtzahl der Seiten des Dokuments festhält:

In einer Produktionsanwendung würden Sie den Wert pageCount in der Regel direkt verwenden, statt ihn in eine Datei zu schreiben – zum Beispiel, um einen Upload zu validieren, eine Schleifengrenze festzulegen oder Metadaten in der Benutzeroberfläche anzuzeigen. Der hier gezeigte Ansatz mit Dateiausgabe ist für Tests und Demonstrationen nützlich.
Physische Seitenzahl vs. Seitenbeschriftungen
Hier ist eine Situation, die Entwickler oft überrascht: Sie lesen Pages.Count aus und erhalten 12, doch der PDF-Reader auf dem Bildschirm des Nutzers zeigt die letzte Seite als „Seite 8“ an. Welche Zahl ist richtig?
Beide sind es – sie messen unterschiedliche Dinge. Pages.Count gibt schlicht und einfach die Anzahl der physischen Seiten im Dokument zurück. Die von einem Reader angezeigte Zahl stammt dagegen aus den Seitenbeschriftungen (dem Eintrag /PageLabels in der PDF-Spezifikation). Seitenbeschriftungen sind eine Darstellungsebene, mit der Verlage steuern, wie Seitenzahlen dem Leser erscheinen. Ein Buchverlag könnte das Cover von der Nummerierung ausnehmen, römische Ziffern (i, ii, iii) für den Vorspann verwenden und den Hauptteil wieder bei 1 beginnen lassen. Nach alledem könnte die fünfte physische Seite je nach Konfiguration der Beschriftungen als iii oder 1 angezeigt werden.
Dieser Unterschied ist wichtig, wenn Ihre Anwendung Nutzern eine Seitenzahl anzeigen soll, die mit dem übereinstimmt, was sie in ihrem Reader sehen. Wenn Sie Pages.Count als „aktuelle Seite“ anzeigen, stimmt das nicht mit der Nummerierung des Readers überein, sobald Seitenbeschriftungen im Spiel sind.
Wenn Sie die angezeigte Beschriftung statt des physischen Index benötigen, lesen Sie die Eigenschaft PageLabel des einzelnen Seitenobjekts aus:
// What label the 5th physical page displays in a reader
const page = doc.Pages.get_Item(4);
console.log(page.PageLabel);
Beachten Sie den nullbasierten Index: get_Item(4) ruft die fünfte physische Seite ab. Wenn im Dokument keine Seitenbeschriftungen konfiguriert sind, gibt PageLabel eine leere Zeichenkette zurück. In diesem häufigen Fall entspricht die angezeigte Zahl der physischen Seitenreihenfolge, sodass Count der gewünschte Wert ist.
Ein praktischer Weg, beide Szenarien zu behandeln, besteht darin, zuerst PageLabel zu prüfen und auf den physischen Index zurückzugreifen, wenn er leer ist. So erhält Ihre Anwendung immer eine Seitenzahl, die dem entspricht, was der Nutzer sieht – unabhängig davon, ob das Dokument benutzerdefinierte Beschriftungen verwendet.
Seiten in einem verschlüsselten PDF zählen
Viele PDFs in Unternehmensumgebungen sind durch ein Öffnungspasswort geschützt – eine Sicherheitsmaßnahme, die verhindert, dass das Dokument ohne die korrekten Zugangsdaten gelesen wird. Wenn Sie versuchen, eine solche Datei mit einem einfachen LoadFromFile-Aufruf zu laden, wirft die WASM-Laufzeit einen Fehler, bevor Pages.Count überhaupt erreicht wird:
Can not open an encrypted document. The password is invalid.
Dies geschieht beim Laden, nicht an der Stelle, an der Sie die Seitenzahl auslesen. Der Inhalt des Dokuments – einschließlich seiner Seitenstruktur – ist verschlüsselt, sodass die Bibliothek ihn ohne das Passwort nicht parsen kann. Es gibt keine Möglichkeit, Seiten zu zählen, ohne das Dokument zuvor zu entsperren.
Die Lösung ist unkompliziert: Übergeben Sie das Öffnungspasswort als zweites Argument an LoadFromFile. Sobald das Dokument entsperrt ist, ist die Seitenzahl genauso verfügbar wie bei einer unverschlüsselten Datei:
// The second argument is the open password
doc.LoadFromFile(inputFileName, 'spire123');
const pageCount = doc.Pages.Count;
In einer echten Anwendung würden Sie das Passwort in der Regel über ein Formularfeld vom Nutzer abfragen und dynamisch übergeben, statt es fest im Code zu hinterlegen. Wenn der Nutzer das falsche Passwort eingibt, wird derselbe Fehler geworfen – daher ist es gute Praxis, den LoadFromFile-Aufruf in einen try/catch-Block zu packen und eine freundliche Meldung wie „falsches Passwort“ anzuzeigen.
Noch ein erwähnenswerter Punkt: Dieses Passwort ist das Öffnungspasswort (auch Benutzerpasswort genannt), das steuert, wer das Dokument ansehen darf. Ein PDF kann außerdem ein Berechtigungspasswort (Besitzerpasswort) haben, das Bearbeiten, Drucken oder Kopieren einschränkt, ohne das Ansehen zu blockieren. Für das Zählen von Seiten ist nur das Öffnungspasswort relevant – sobald das Dokument geöffnet ist, funktioniert Pages.Count unabhängig von Berechtigungseinschränkungen.
Die Seitenzahl als Schleifengrenze verwenden
Sobald Sie die Seitenzahl haben, ist der nächste naheliegende Schritt, über jede Seite zu iterieren – um Text zu extrahieren, Miniaturansichten zu rendern, das Dokument zu teilen oder eine Transformation anzuwenden. Genau hier taucht ein subtiler, aber häufiger Fehler auf: die Verwendung von Count als inklusive Obergrenze.
Die Sammlung Pages ist nullbasiert indiziert, das heißt, gültige Indizes reichen von 0 bis Count - 1. Wenn die Schleifenbedingung mit <= statt mit < geschrieben wird, versucht die letzte Iteration, auf die Seite am Index Count zuzugreifen, die nicht existiert. Die WASM-Laufzeit verpackt die zugrunde liegende .NET-ArgumentOutOfRangeException als JavaScript-Error mit einer Meldung wie:
ArgumentOutOfRange_IndexMustBeLess Arg_ParamName_Name, index
Da die Eigenschaft name des Fehlers nur das generische Error ist, können Sie ihn nicht allein anhand des Namens unterscheiden – Sie müssen auf die Meldungszeichenkette prüfen, wenn Sie ihn gezielt behandeln möchten.
Die korrekte Schleife verwendet <, sodass der zuletzt zugegriffene Index Count - 1 ist:
// 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);
}
Dieses Off-by-one-Muster ist eine der häufigsten Ursachen für Laufzeitfehler bei der Arbeit mit Seitensammlungen. In Tests übersieht man es leicht, wenn Ihre Beispieldokumente zufällig nur ein oder zwei Seiten haben – der Fehler tritt nur in der letzten Iteration auf, sodass ein einseitiges Dokument ihn überhaupt nicht auslöst. Testen Sie die Schleifenlogik immer mit einem Dokument, das mindestens drei Seiten hat, um sicherzustellen, dass die Grenzbedingung korrekt ist.
Siehe auch
- Spire.PDF für JavaScript in ein React-Projekt integrieren — Einrichtungsanleitung zum Installieren von Spire.PDF und Initialisieren des WebAssembly-Moduls in einer React-App.
- Produktseite von Spire.PDF für JavaScript — Überblick über Funktionen, unterstützte Vorgänge und browserbasierte PDF-Verarbeitungsmöglichkeiten.
- spire.pdf auf npm — Paketseite zum Installieren der Bibliothek über npm.
Подсчёт страниц PDF в JavaScript: больше, чем просто число

Одно целое число — общее количество страниц в PDF — стоит за удивительно большим числом реальных решений: ограничения на загрузку, оценка бумаги для печати, операции разделения, индикаторы выполнения. Большинство библиотек отрисовки PDF только отрисовывают страницы и не предоставляют простого счётчика, а отправка файла на серверную часть только для чтения количества страниц добавляет задержку и вызывает вопросы конфиденциальности.
Spire.PDF для JavaScript загружает и анализирует PDF-документы непосредственно в браузере через WebAssembly, поэтому файл никогда не покидает клиент. Количество страниц доступно как одно свойство — никаких циклов, никаких обращений к серверу, никаких обходных путей отрисовки. В этой статье рассматривается получение этого количества и три практических вопроса: отличие физического количества страниц от отображаемых меток, обработка файлов, защищённых паролем, и избежание ошибок на единицу при переборе страниц.
Для установки и настройки проекта см. Интеграция Spire.PDF для JavaScript в проект React. Примеры ниже предполагают, что Spire.PDF установлен и модуль WebAssembly инициализирован.
Получение количества страниц PDF-документа
После того как объект PdfDocument загрузил файл, его свойство Pages предоставляет коллекцию страниц, а свойство Count этой коллекции возвращает общее количество страниц. Нет необходимости перебирать страницы по отдельности — количество доступно сразу после загрузки.
Следующий компонент React демонстрирует полный рабочий процесс: получение PDF в виртуальную файловую систему, создание PdfDocument, загрузка файла, чтение Pages.Count и запись результата в текстовый файл для скачивания.
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;
Результат записывается в текстовый файл, в котором фиксируется общее количество страниц документа:

В производственном приложении вы обычно использовали бы значение pageCount напрямую, а не записывали его в файл — например, для проверки загрузки, установки границы цикла или отображения метаданных в интерфейсе. Показанный здесь подход с выводом в файл полезен для тестирования и демонстрации.
Физическое количество страниц и метки страниц
Вот ситуация, которая застаёт разработчиков врасплох: вы читаете Pages.Count и получаете 12, но PDF-ридер на экране пользователя показывает последнюю страницу как «страница 8». Какое число правильное?
Оба — они измеряют разные вещи. Pages.Count возвращает количество физических страниц в документе, и ничего больше. Однако число, отображаемое ридером, происходит от меток страниц (запись /PageLabels в спецификации PDF). Метки страниц — это слой представления, который издатели используют для управления тем, как номера страниц отображаются читателю. Издатель книги может исключить обложку из нумерации, использовать римские цифры (i, ii, iii) для вводной части и начать основную часть заново с 1. В результате пятая физическая страница может отображаться как iii или 1 в зависимости от того, как настроены метки.
Это различие имеет значение, когда ваше приложение должно показывать пользователям номер страницы, совпадающий с тем, что они видят в своём ридере. Если вы отображаете Pages.Count как «текущую страницу», оно не будет совпадать с нумерацией ридера всякий раз, когда используются метки страниц.
Когда вам нужна отображаемая метка, а не физический индекс, прочитайте свойство PageLabel у отдельного объекта страницы:
// What label the 5th physical page displays in a reader
const page = doc.Pages.get_Item(4);
console.log(page.PageLabel);
Обратите внимание на индекс с отсчётом от нуля: get_Item(4) извлекает пятую физическую страницу. Когда в документе не настроены метки страниц, PageLabel возвращает пустую строку. В этом распространённом случае отображаемое число совпадает с порядком физических страниц, поэтому Count — это нужное вам значение.
Практичный способ обработки обоих сценариев — сначала проверить PageLabel и вернуться к физическому индексу, когда оно пустое. Это даёт вашему приложению номер страницы, который всегда совпадает с тем, что видит пользователь, независимо от того, использует ли документ пользовательские метки.
Подсчёт страниц в зашифрованном PDF
Многие PDF-файлы в бизнес-среде защищены паролем на открытие — мерой безопасности, которая не позволяет прочитать документ без правильных учётных данных. Если вы попытаетесь загрузить такой файл обычным вызовом LoadFromFile, среда выполнения WASM выдаст ошибку ещё до того, как будет достигнуто Pages.Count:
Не удаётся открыть зашифрованный документ. Пароль неверен.
Это происходит во время загрузки, а не в тот момент, когда вы читаете количество страниц. Содержимое документа — включая его структуру страниц — зашифровано, поэтому библиотека не может его разобрать без пароля. Невозможно подсчитать страницы, не разблокировав документ.
Решение простое: передайте пароль на открытие вторым аргументом в LoadFromFile. Как только документ разблокирован, количество страниц доступно так же, как и для незашифрованного файла:
// The second argument is the open password
doc.LoadFromFile(inputFileName, 'spire123');
const pageCount = doc.Pages.Count;
В реальном приложении вы обычно собирали бы пароль у пользователя через поле формы и передавали бы его динамически, а не жёстко зашивали. Если пользователь введёт неправильный пароль, будет выброшена та же ошибка — поэтому обернуть вызов LoadFromFile в блок try/catch и показать дружественное сообщение «неверный пароль» — хорошая практика.
Ещё одна вещь, которую стоит отметить: этот пароль — пароль на открытие (также называемый паролем пользователя), который определяет, кто может просматривать документ. PDF также может иметь пароль разрешений (пароль владельца), который ограничивает редактирование, печать или копирование, не блокируя просмотр. Для подсчёта страниц важен только пароль на открытие — как только документ открыт, Pages.Count работает независимо от ограничений разрешений.
Использование количества страниц в качестве границы цикла
Получив количество страниц, естественный следующий шаг — перебрать каждую страницу: извлечь текст, отрисовать миниатюры, разделить документ или применить какое-либо преобразование. Именно здесь появляется тонкая, но распространённая ошибка: использование Count в качестве включающей верхней границы.
Коллекция Pages имеет индексацию с нуля, то есть допустимые индексы идут от 0 до Count - 1. Если условие цикла записано с <= вместо <, последняя итерация попытается обратиться к странице с индексом Count, которой не существует. Среда выполнения WASM оборачивает базовое исключение .NET ArgumentOutOfRangeException в JavaScript Error с сообщением вроде:
ArgumentOutOfRange_IndexMustBeLess Arg_ParamName_Name, index
Поскольку свойство name этой ошибки — просто общее Error, вы не можете отличить её только по имени — вам придётся сопоставлять строку сообщения, если вы хотите обработать её особым образом.
Правильный цикл использует <, поэтому последний используемый индекс — 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);
}
Эта ошибка на единицу — один из наиболее частых источников ошибок времени выполнения при работе с коллекциями страниц. Её легко пропустить при тестировании, если ваши образцы документов содержат только одну или две страницы — ошибка проявляется только на последней итерации, поэтому документ с одной страницей её вообще не вызовет. Всегда тестируйте логику цикла на документе, содержащем как минимум три страницы, чтобы убедиться, что граничное условие верно.
См. также
- Интеграция Spire.PDF для JavaScript в проект React — Руководство по настройке установки Spire.PDF и инициализации модуля WebAssembly в приложении React.
- Страница продукта Spire.PDF для JavaScript — Обзор функций, поддерживаемых операций и возможностей обработки PDF в браузере.
- spire.pdf на npm — Страница пакета для установки библиотеки через npm.
Ler valores de campos de formulário PDF por tipo com JavaScript

Quando alguém preenche um formulário PDF e o salva, os valores inseridos ficam dentro das estruturas de campos do documento — não como texto simples que você possa pesquisar ou copiar em massa. Para um formulário com trinta ou quarenta campos, a transcrição manual torna-se um gargalo. O problema mais profundo é que cada tipo de campo armazena seu valor de maneira diferente: uma caixa de texto expõe uma string, uma caixa de seleção reporta um booleano, uma caixa de combinação separa as opções da seleção, e um botão de opção armazena o item escolhido. Não existe uma única chamada uniforme de "me dê o valor".
Este artigo mostra como extrair valores de campos de formulário de um PDF usando o Spire.PDF for JavaScript. A biblioteca é executada em WebAssembly no navegador, então o documento é analisado localmente por meio de um sistema de arquivos virtual, sem ida e volta ao servidor. Você verá como percorrer a coleção de campos, identificar o tipo de cada campo e ler a propriedade correta para caixas de texto, caixas de lista, caixas de combinação, botões de opção e caixas de seleção.
Para configuração e instalação do projeto, consulte Integrate Spire.PDF for JavaScript in a React Project. O código abaixo pressupõe que o Spire.PDF está instalado e o módulo WASM está inicializado.
Tipos de Campo em Resumo
Antes de mergulhar na implementação, ajuda mapear como cada tipo de campo expõe seu valor. O Spire.PDF for JavaScript representa campos de formulário como classes de widget, e a propriedade que contém o valor atual difere de um tipo para outro:
| Tipo de Campo | Classe de Widget | Propriedade de Leitura | Observações |
|---|---|---|---|
| Caixa de Texto | PdfTextBoxFieldWidget |
Text |
Retorna a string inserida diretamente. |
| Caixa de Lista | PdfListBoxWidgetFieldWidget |
SelectedValue |
Values é a lista completa de opções, não a escolha do usuário. |
| Caixa de Combinação | PdfComboBoxWidgetFieldWidget |
SelectedValue |
Mesmo modelo de propriedade dupla da caixa de lista. |
| Botão de Opção | PdfRadioButtonListFieldWidget |
Value |
Fornece a string do item selecionado em uma única etapa. |
| Caixa de Seleção | PdfCheckBoxWidgetFieldWidget |
Checked |
Estado booleano. Value é undefined — não o use. |
O padrão é claro: não existe uma única propriedade universal. A lógica de extração deve testar o tipo de cada campo e ler a propriedade correspondente, que é exatamente o que a próxima seção implementa.
Iterar Campos e Ler por Tipo
O fluxo de trabalho principal tem três etapas: carregar o PDF, obter seu formulário como um PdfFormWidget e então percorrer a coleção FieldsWidget e ramificar pelo tipo de cada campo com instanceof. Em cada ramificação, leia a propriedade específica do tipo e acrescente o resultado a uma string de relatório. Como a distribuição cobre todos os tipos suportados, você não precisa saber de antemão quais campos o documento contém — campos não reconhecidos simplesmente caem em um rótulo padrão.
function App() {
const getAllFieldValues = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check that the module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load the PDF file to be read into the VFS
const inputFileName = 'ApplicationForm.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);
// Build a PdfFormWidget from the document's form handle; FieldsWidget is its field collection
const formWidget = new pdfModule.PdfFormWidget(doc.Form.H);
const fields = formWidget.FieldsWidget;
let report = '';
// Walk the field collection, check each type, and read the matching value
for (let i = 0; i < fields.Count; i++) {
const field = fields.get_Item({ index: i });
// Both the type name and the value are filled in by the type dispatch
let type = 'Unknown';
let value = '(Unrecognized field type)';
if (field instanceof pdfModule.PdfTextBoxFieldWidget) {
// Text box field: read Text directly
type = 'TextBox';
value = field.Text;
} else if (field instanceof pdfModule.PdfListBoxWidgetFieldWidget) {
// List box field: Values holds every option, SelectedValue is the current one
const options = [];
for (let j = 0; j < field.Values.Count; j++) {
options.push(field.Values.get_Item(j).Value);
}
type = 'ListBox';
value = `Selected ${field.SelectedValue}, options ${options.join(', ')}`;
} else if (field instanceof pdfModule.PdfComboBoxWidgetFieldWidget) {
// Combo box field: like a list box, it has an option collection and a selected value
const options = [];
for (let j = 0; j < field.Values.Count; j++) {
options.push(field.Values.get_Item(j).Value);
}
type = 'ComboBox';
value = `Selected ${field.SelectedValue}, options ${options.join(', ')}`;
} else if (field instanceof pdfModule.PdfRadioButtonListFieldWidget) {
// Radio button field: Value is the selected item
type = 'RadioButton';
value = `Selected ${field.Value}`;
} else if (field instanceof pdfModule.PdfCheckBoxWidgetFieldWidget) {
// Check box field: Checked gives the state, not Value
type = 'CheckBox';
value = field.Checked ? 'Checked' : 'Not checked';
}
report += `Field "${field.Name}" (${type}): ${value}\n`;
}
const outputFileName = 'AllFieldValues.txt';
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>Extract Form Field Values</h1>
<button onClick={getAllFieldValues}>
Extract values
</button>
</div>
);
}
export default App;
Depois que o loop termina, a string de relatório contém uma linha por campo com seu nome, tipo e valor atual. O arquivo é gravado no sistema de arquivos virtual e então baixado como um arquivo de texto:

A cadeia de instanceof é o coração da abordagem. Cada ramificação sabe exatamente qual propriedade ler, então a saída fica correta independentemente de quantos tipos de campo o documento mistura. As próximas três seções abordam as armadilhas que surgem quando a propriedade de valor de um campo não é a que você poderia esperar.
Caixas de Seleção: Checked vs Value
Um erro comum ao ler campos de caixa de seleção é recorrer a uma propriedade Value. O widget de caixa de seleção — PdfCheckBoxWidgetFieldWidget — não expõe Value de forma alguma; tentar lê-lo retorna undefined. Nos bastidores, uma caixa de seleção rastreia seu estado por meio de valores de exportação: Off quando não marcada, e Yes ou uma string de exportação personalizada quando marcada. Uma string bruta não consegue dizer de forma confiável se a caixa está selecionada, então a superfície da API deliberadamente omite Value e oferece Checked em vez disso.
A correção é simples — use sempre a propriedade booleana Checked:
// Check the state with Checked, not Value
const checked = field.Checked;
Isso retorna true quando a caixa está marcada e false caso contrário, fornecendo um booleano limpo para a lógica subsequente, sem qualquer análise de string.
Caixas de Lista e Caixas de Combinação: SelectedValue vs Values
Caixas de lista e caixas de combinação compartilham um modelo de dados em duas partes que confunde muitos desenvolvedores. Tanto PdfListBoxWidgetFieldWidget quanto PdfComboBoxWidgetFieldWidget expõem uma coleção Values e uma string SelectedValue, e é fácil supor que Values contém a entrada do usuário. Não contém.
Values é o conjunto completo de opções disponíveis. Cada elemento da coleção é um objeto PdfListWidgetItem, então você deve desempacotá-lo com .Value para obter o texto da opção. Percorrer Values informa o que o usuário poderia ter escolhido, não o que ele realmente selecionou. A seleção real do usuário está em SelectedValue como uma string simples.
Use SelectedValue para o valor atual e percorra Values apenas quando precisar enumerar as escolhas disponíveis:
// The text of the currently selected item
const selected = field.SelectedValue;
// Every available option
const options = [];
for (let j = 0; j < field.Values.Count; j++) {
options.push(field.Values.get_Item(j).Value);
}
Manter essas duas propriedades bem distintas é essencial: tratar Values como a resposta fornece a lista de opções em vez do resultado preenchido, e as duas raramente têm o mesmo comprimento.
Lidar com PDFs Criptografados
A extração de formulário começa abrindo o documento. Se o PDF estiver protegido por senha, chamar LoadFromFile apenas com o nome do arquivo lança um erro — "Can not open an encrypted document. The password is invalid." — e nenhum objeto de documento é retornado. Os campos de formulário nunca são alcançados.
A solução é passar a senha de abertura como o segundo argumento:
doc.LoadFromFile(inputFileName, 'spire123');
Depois que o documento abre com sucesso, o restante do fluxo de extração — construir o PdfFormWidget, percorrer os campos, distribuir por tipo — funciona exatamente da mesma forma que com um arquivo não criptografado. A senha apenas bloqueia o carregamento inicial; ela não altera como os valores dos campos são lidos.
Veja Também
- Integrate Spire.PDF for JavaScript in a React Project — configuração, instalação e inicialização do WASM
- Fill PDF Form Fields with Spire.PDF for JavaScript — gravar valores em campos de formulário programaticamente
- Import and Export PDF Form Data with Spire.PDF for JavaScript — serializar dados de formulário em arquivos FDF/XFDF
Se você quiser remover a mensagem de avaliação do documento resultante, ou eliminar as limitações de recursos, entre em contato com a equipe de vendas para obter uma licença temporária válida por 30 dias.
JavaScript로 유형별 PDF 양식 필드 값 읽기

누군가 PDF 양식을 작성하고 저장하면, 입력된 값은 문서의 필드 구조 안에 저장됩니다. 일괄적으로 검색하거나 복사할 수 있는 일반 텍스트가 아닙니다. 서른 개나 마흔 개의 필드가 있는 양식이라면 손으로 옮겨 적는 작업이 병목이 됩니다. 더 근본적인 문제는 각 필드 유형이 값을 저장하는 방식이 서로 다르다는 점입니다. 텍스트 상자는 문자열을 노출하고, 체크 박스는 불리언을 보고하며, 콤보 상자는 옵션과 선택 항목을 분리하고, 라디오 버튼은 선택된 항목을 저장합니다. 하나의 통일된 "값을 달라"는 호출은 존재하지 않습니다.
이 글에서는 Spire.PDF for JavaScript를 사용하여 PDF에서 양식 필드 값을 추출하는 방법을 살펴봅니다. 이 라이브러리는 브라우저에서 WebAssembly로 실행되므로, 문서가 가상 파일 시스템을 통해 로컬에서 구문 분석되며 서버 왕복이 필요하지 않습니다. 필드 컬렉션을 순회하고, 각 필드의 유형에 따라 분기하고, 텍스트 상자, 목록 상자, 콤보 상자, 라디오 버튼, 체크 박스에 대해 올바른 속성을 읽는 방법을 확인할 수 있습니다.
설정 및 프로젝트 구성에 대해서는 React 프로젝트에 Spire.PDF for JavaScript 통합하기를 참조하세요. 아래 코드는 Spire.PDF가 설치되어 있고 WASM 모듈이 초기화되었다고 가정합니다.
필드 유형 한눈에 보기
구현을 살펴보기 전에 각 필드 유형이 값을 어떻게 노출하는지 정리해 두면 도움이 됩니다. Spire.PDF for JavaScript는 양식 필드를 위젯 클래스로 표현하며, 현재 값을 담고 있는 속성은 유형마다 다릅니다.
| 필드 유형 | 위젯 클래스 | 읽을 속성 | 비고 |
|---|---|---|---|
| 텍스트 상자 | PdfTextBoxFieldWidget |
Text |
입력된 문자열을 그대로 반환합니다. |
| 목록 상자 | PdfListBoxWidgetFieldWidget |
SelectedValue |
Values는 전체 옵션 목록이며, 사용자가 선택한 항목이 아닙니다. |
| 콤보 상자 | PdfComboBoxWidgetFieldWidget |
SelectedValue |
목록 상자와 동일한 이중 속성 모델을 사용합니다. |
| 라디오 버튼 | PdfRadioButtonListFieldWidget |
Value |
선택된 항목 문자열을 한 번에 제공합니다. |
| 체크 박스 | PdfCheckBoxWidgetFieldWidget |
Checked |
불리언 상태입니다. Value는 undefined이므로 사용하지 마세요. |
패턴은 분명합니다. 모든 경우에 통용되는 단일 속성은 없습니다. 추출 로직은 각 필드의 유형을 확인하고 그에 맞는 속성을 읽어야 하며, 다음 섹션에서 바로 그것을 구현합니다.
필드 반복 및 유형별 값 읽기
핵심 워크플로는 세 단계로 이루어집니다. PDF를 로드하고, 양식을 PdfFormWidget으로 가져온 다음, FieldsWidget 컬렉션을 순회하면서 instanceof로 각 필드의 클래스에 따라 분기합니다. 각 분기에서 유형별 속성을 읽고 결과를 보고서 문자열에 추가합니다. 이 분기 처리가 지원되는 모든 유형을 다루므로, 문서에 어떤 필드가 들어 있는지 미리 알 필요가 없습니다. 인식되지 않는 필드는 단순히 기본 레이블로 처리됩니다.
function App() {
const getAllFieldValues = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check that the module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load the PDF file to be read into the VFS
const inputFileName = 'ApplicationForm.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);
// Build a PdfFormWidget from the document's form handle; FieldsWidget is its field collection
const formWidget = new pdfModule.PdfFormWidget(doc.Form.H);
const fields = formWidget.FieldsWidget;
let report = '';
// Walk the field collection, check each type, and read the matching value
for (let i = 0; i < fields.Count; i++) {
const field = fields.get_Item({ index: i });
// Both the type name and the value are filled in by the type dispatch
let type = 'Unknown';
let value = '(Unrecognized field type)';
if (field instanceof pdfModule.PdfTextBoxFieldWidget) {
// Text box field: read Text directly
type = 'TextBox';
value = field.Text;
} else if (field instanceof pdfModule.PdfListBoxWidgetFieldWidget) {
// List box field: Values holds every option, SelectedValue is the current one
const options = [];
for (let j = 0; j < field.Values.Count; j++) {
options.push(field.Values.get_Item(j).Value);
}
type = 'ListBox';
value = `Selected ${field.SelectedValue}, options ${options.join(', ')}`;
} else if (field instanceof pdfModule.PdfComboBoxWidgetFieldWidget) {
// Combo box field: like a list box, it has an option collection and a selected value
const options = [];
for (let j = 0; j < field.Values.Count; j++) {
options.push(field.Values.get_Item(j).Value);
}
type = 'ComboBox';
value = `Selected ${field.SelectedValue}, options ${options.join(', ')}`;
} else if (field instanceof pdfModule.PdfRadioButtonListFieldWidget) {
// Radio button field: Value is the selected item
type = 'RadioButton';
value = `Selected ${field.Value}`;
} else if (field instanceof pdfModule.PdfCheckBoxWidgetFieldWidget) {
// Check box field: Checked gives the state, not Value
type = 'CheckBox';
value = field.Checked ? 'Checked' : 'Not checked';
}
report += `Field "${field.Name}" (${type}): ${value}\n`;
}
const outputFileName = 'AllFieldValues.txt';
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>Extract Form Field Values</h1>
<button onClick={getAllFieldValues}>
Extract values
</button>
</div>
);
}
export default App;
루프가 끝나면 보고서 문자열에는 각 필드의 이름, 유형, 현재 값이 한 줄씩 담깁니다. 이 파일은 가상 파일 시스템에 기록된 다음 텍스트 파일로 다운로드됩니다.

instanceof 분기 체인이 이 접근 방식의 핵심입니다. 각 분기는 읽어야 할 속성을 정확히 알고 있으므로, 문서에 얼마나 많은 필드 유형이 섞여 있든 출력은 올바릅니다. 다음 세 섹션에서는 필드의 값 속성이 예상과 다를 때 발생하는 함정을 다룹니다.
체크 박스: Checked와 Value의 차이
체크 박스 필드를 읽을 때 흔히 하는 실수는 Value 속성을 사용하려는 것입니다. 체크 박스 위젯인 PdfCheckBoxWidgetFieldWidget은 Value를 전혀 노출하지 않으며, 이를 읽으려 하면 undefined가 반환됩니다. 내부적으로 체크 박스는 내보내기 값(export value)을 통해 상태를 추적합니다. 선택되지 않았을 때는 Off이고, 선택되었을 때는 Yes 또는 사용자 지정 내보내기 문자열입니다. 원시 문자열만으로는 상자가 선택되었는지 확실히 알 수 없으므로, API는 의도적으로 Value를 생략하고 대신 Checked를 제공합니다.
해결 방법은 간단합니다. 항상 불리언인 Checked 속성을 사용하세요.
// Check the state with Checked, not Value
const checked = field.Checked;
이 속성은 상자가 선택되어 있으면 true, 그렇지 않으면 false를 반환하므로, 문자열 구문 분석 없이 후속 로직에 사용할 깔끔한 불리언 값을 얻을 수 있습니다.
목록 상자와 콤보 상자: SelectedValue와 Values의 차이
목록 상자와 콤보 상자는 많은 개발자를 헷갈리게 하는 두 부분으로 된 데이터 모델을 공유합니다. PdfListBoxWidgetFieldWidget과 PdfComboBoxWidgetFieldWidget 모두 Values 컬렉션과 SelectedValue 문자열을 노출하는데, Values에 사용자의 입력이 들어 있다고 가정하기 쉽습니다. 그렇지 않습니다.
Values는 사용 가능한 모든 옵션의 집합입니다. 컬렉션의 각 요소는 PdfListWidgetItem 객체이므로, 옵션 텍스트를 얻으려면 .Value로 풀어내야 합니다. Values를 순회하면 사용자가 선택할 수 있었던 항목을 알 수 있을 뿐, 실제로 선택한 항목은 아닙니다. 사용자의 실제 선택은 일반 문자열인 SelectedValue에 있습니다.
현재 값에는 SelectedValue를 사용하고, 사용 가능한 선택지를 열거해야 할 때만 Values를 순회하세요.
// The text of the currently selected item
const selected = field.SelectedValue;
// Every available option
const options = [];
for (let j = 0; j < field.Values.Count; j++) {
options.push(field.Values.get_Item(j).Value);
}
이 두 속성을 정확히 구분하는 것이 중요합니다. Values를 답으로 취급하면 채워진 결과 대신 옵션 목록을 얻게 되며, 이 둘은 길이가 같은 경우가 거의 없습니다.
암호화된 PDF 처리
양식 추출은 문서를 여는 것에서 시작합니다. PDF가 암호로 보호되어 있다면 파일 이름만으로 LoadFromFile을 호출할 때 오류가 발생합니다. — "Can not open an encrypted document. The password is invalid." — 그리고 문서 객체가 반환되지 않습니다. 양식 필드에는 아예 도달하지 못합니다.
해결 방법은 열기 암호를 두 번째 인수로 전달하는 것입니다.
doc.LoadFromFile(inputFileName, 'spire123');
문서가 성공적으로 열리면 나머지 추출 흐름 — PdfFormWidget 생성, 필드 순회, 유형별 분기 처리 — 은 암호화되지 않은 파일과 완전히 동일하게 작동합니다. 암호는 최초 로드만 제한할 뿐, 필드 값을 읽는 방식에는 영향을 주지 않습니다.
관련 항목
- React 프로젝트에 Spire.PDF for JavaScript 통합하기 — 설정, 설치, WASM 초기화
- Spire.PDF for JavaScript로 PDF 양식 필드 채우기 — 양식 필드에 값을 프로그래밍 방식으로 기록
- Spire.PDF for JavaScript로 PDF 양식 데이터 가져오기 및 내보내기 — 양식 데이터를 FDF/XFDF 파일로 직렬화
결과 문서에서 평가 메시지를 제거하거나 기능 제한을 없애려면, 30일 동안 유효한 임시 라이선스를 위해 영업팀에 문의하세요.
Leggere i valori dei campi modulo PDF per tipo con JavaScript
Indice dei contenuti

Quando qualcuno compila un modulo PDF e lo salva, i valori inseriti risiedono all'interno delle strutture dei campi del documento — non come testo semplice che puoi cercare o copiare in blocco. Per un modulo con trenta o quaranta campi, la trascrizione manuale diventa un collo di bottiglia. Il problema più profondo è che ogni tipo di campo memorizza il proprio valore in modo diverso: una casella di testo espone una stringa, una casella di controllo restituisce un booleano, una casella combinata separa le opzioni dalla selezione e un pulsante di opzione memorizza l'elemento scelto. Non esiste una singola chiamata uniforme "dammi il valore".
Questo articolo illustra come estrarre i valori dei campi modulo da un PDF usando Spire.PDF per JavaScript. La libreria viene eseguita su WebAssembly nel browser, quindi il documento viene analizzato localmente tramite un file system virtuale senza alcun round-trip verso il server. Vedrai come scorrere la raccolta di campi, effettuare il dispatch in base al tipo di ciascun campo e leggere la proprietà corretta per caselle di testo, caselle di riepilogo, caselle combinate, pulsanti di opzione e caselle di controllo.
Per l'installazione e la configurazione del progetto, consulta Integrare Spire.PDF per JavaScript in un progetto React. Il codice seguente presuppone che Spire.PDF sia installato e che il modulo WASM sia inizializzato.
Tipi di campo a colpo d'occhio
Prima di immergerti nell'implementazione, è utile mappare come ogni tipo di campo espone il proprio valore. Spire.PDF per JavaScript rappresenta i campi modulo come classi widget, e la proprietà che contiene il valore corrente varia da un tipo all'altro:
| Tipo di campo | Classe widget | Proprietà da leggere | Note |
|---|---|---|---|
| Casella di testo | PdfTextBoxFieldWidget |
Text |
Restituisce direttamente la stringa inserita. |
| Casella di riepilogo | PdfListBoxWidgetFieldWidget |
SelectedValue |
Values è l'elenco completo delle opzioni, non la scelta dell'utente. |
| Casella combinata | PdfComboBoxWidgetFieldWidget |
SelectedValue |
Stesso modello a doppia proprietà della casella di riepilogo. |
| Pulsante di opzione | PdfRadioButtonListFieldWidget |
Value |
Fornisce la stringa dell'elemento selezionato in un unico passaggio. |
| Casella di controllo | PdfCheckBoxWidgetFieldWidget |
Checked |
Stato booleano. Value è undefined — non usarlo. |
Il modello è chiaro: non esiste un'unica proprietà universale. La logica di estrazione deve verificare il tipo di ciascun campo e leggere la proprietà corrispondente, che è esattamente ciò che implementa la sezione successiva.
Iterare i campi e leggere per tipo
Il flusso di lavoro principale prevede tre passaggi: caricare il PDF, ottenere il suo modulo come PdfFormWidget, quindi scorrere la raccolta FieldsWidget e diramare in base alla classe di ciascun campo con instanceof. In ogni ramo, leggi la proprietà specifica del tipo e aggiungi il risultato a una stringa di report. Poiché il dispatch copre ogni tipo supportato, non è necessario sapere in anticipo quali campi contiene il documento — i campi non riconosciuti ricadono semplicemente in un'etichetta predefinita.
function App() {
const getAllFieldValues = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check that the module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load the PDF file to be read into the VFS
const inputFileName = 'ApplicationForm.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);
// Build a PdfFormWidget from the document's form handle; FieldsWidget is its field collection
const formWidget = new pdfModule.PdfFormWidget(doc.Form.H);
const fields = formWidget.FieldsWidget;
let report = '';
// Walk the field collection, check each type, and read the matching value
for (let i = 0; i < fields.Count; i++) {
const field = fields.get_Item({ index: i });
// Both the type name and the value are filled in by the type dispatch
let type = 'Unknown';
let value = '(Unrecognized field type)';
if (field instanceof pdfModule.PdfTextBoxFieldWidget) {
// Text box field: read Text directly
type = 'TextBox';
value = field.Text;
} else if (field instanceof pdfModule.PdfListBoxWidgetFieldWidget) {
// List box field: Values holds every option, SelectedValue is the current one
const options = [];
for (let j = 0; j < field.Values.Count; j++) {
options.push(field.Values.get_Item(j).Value);
}
type = 'ListBox';
value = `Selected ${field.SelectedValue}, options ${options.join(', ')}`;
} else if (field instanceof pdfModule.PdfComboBoxWidgetFieldWidget) {
// Combo box field: like a list box, it has an option collection and a selected value
const options = [];
for (let j = 0; j < field.Values.Count; j++) {
options.push(field.Values.get_Item(j).Value);
}
type = 'ComboBox';
value = `Selected ${field.SelectedValue}, options ${options.join(', ')}`;
} else if (field instanceof pdfModule.PdfRadioButtonListFieldWidget) {
// Radio button field: Value is the selected item
type = 'RadioButton';
value = `Selected ${field.Value}`;
} else if (field instanceof pdfModule.PdfCheckBoxWidgetFieldWidget) {
// Check box field: Checked gives the state, not Value
type = 'CheckBox';
value = field.Checked ? 'Checked' : 'Not checked';
}
report += `Field "${field.Name}" (${type}): ${value}\n`;
}
const outputFileName = 'AllFieldValues.txt';
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>Extract Form Field Values</h1>
<button onClick={getAllFieldValues}>
Extract values
</button>
</div>
);
}
export default App;
Dopo che il ciclo è terminato, la stringa del report contiene una riga per campo con il suo nome, il tipo e il valore corrente. Il file viene scritto nel file system virtuale e quindi scaricato come file di testo:

La catena di instanceof è il cuore dell'approccio. Ogni ramo sa esattamente quale proprietà leggere, quindi l'output è corretto indipendentemente da quanti tipi di campo il documento combina insieme. Le tre sezioni successive affrontano le insidie che sorgono quando la proprietà del valore di un campo non è quella che potresti aspettarti.
Caselle di controllo: Checked vs Value
Un errore comune quando si leggono i campi casella di controllo è cercare una proprietà Value. Il widget casella di controllo — PdfCheckBoxWidgetFieldWidget — non espone affatto Value; tentare di leggerla restituisce undefined. Sotto il cofano, una casella di controllo tiene traccia del proprio stato tramite valori di esportazione: Off quando non è selezionata, e Yes o una stringa di esportazione personalizzata quando è selezionata. Una stringa grezza non può indicarti in modo affidabile se la casella è selezionata, quindi l'API omette deliberatamente Value e offre invece Checked.
La soluzione è semplice — usa sempre la proprietà booleana Checked:
// Check the state with Checked, not Value
const checked = field.Checked;
Questa restituisce true quando la casella è selezionata e false in caso contrario, fornendoti un booleano pulito per la logica a valle senza alcuna analisi di stringhe.
Caselle di riepilogo e caselle combinate: SelectedValue vs Values
Le caselle di riepilogo e le caselle combinate condividono un modello dati in due parti che manda in confusione molti sviluppatori. Sia PdfListBoxWidgetFieldWidget sia PdfComboBoxWidgetFieldWidget espongono una raccolta Values e una stringa SelectedValue, ed è facile supporre che Values contenga il valore inserito dall'utente. Non è così.
Values è l'insieme completo delle opzioni disponibili. Ogni elemento della raccolta è un oggetto PdfListWidgetItem, quindi devi estrarlo con .Value per ottenere il testo dell'opzione. Scorrere Values ti dice cosa l'utente poteva scegliere, non cosa ha effettivamente selezionato. La selezione reale dell'utente si trova in SelectedValue come stringa semplice.
Usa SelectedValue per il valore corrente e scorri Values solo quando devi enumerare le scelte disponibili:
// The text of the currently selected item
const selected = field.SelectedValue;
// Every available option
const options = [];
for (let j = 0; j < field.Values.Count; j++) {
options.push(field.Values.get_Item(j).Value);
}
Tenere distinte queste due proprietà è essenziale: trattare Values come la risposta ti dà l'elenco delle opzioni invece del risultato compilato, e le due cose raramente hanno la stessa lunghezza.
Gestione dei PDF crittografati
L'estrazione dei moduli inizia con l'apertura del documento. Se il PDF è protetto da password, chiamare LoadFromFile con il solo nome file genera un errore — "Impossibile aprire un documento crittografato. La password non è valida." — e non viene restituito alcun oggetto documento. I campi modulo non vengono mai raggiunti.
La soluzione è passare la password di apertura come secondo argomento:
doc.LoadFromFile(inputFileName, 'spire123');
Una volta che il documento si apre correttamente, il resto del flusso di estrazione — creare il PdfFormWidget, scorrere i campi, effettuare il dispatch per tipo — funziona esattamente allo stesso modo di un file non crittografato. La password controlla solo il caricamento iniziale; non cambia il modo in cui vengono letti i valori dei campi.
Vedi anche
- Integrare Spire.PDF per JavaScript in un progetto React — configurazione, installazione e inizializzazione WASM
- Compilare i campi modulo PDF con Spire.PDF per JavaScript — scrivere valori nei campi modulo a livello di codice
- Importare ed esportare i dati dei moduli PDF con Spire.PDF per JavaScript — serializzare i dati del modulo in file FDF/XFDF
Se desideri rimuovere il messaggio di valutazione dal documento risultante o eliminare le limitazioni delle funzionalità, contatta l'assistenza commerciale per ottenere una licenza temporanea valida per 30 giorni.
Lire les valeurs des champs de formulaire PDF par type avec JavaScript
Table des matières

Lorsqu'une personne remplit un formulaire PDF et l'enregistre, les valeurs saisies résident dans les structures de champs du document — et non sous forme de texte brut que vous pouvez rechercher ou copier en masse. Pour un formulaire comportant trente ou quarante champs, la transcription manuelle devient un goulot d'étranglement. Le problème plus profond est que chaque type de champ stocke sa valeur différemment : une zone de texte expose une chaîne, une case à cocher renvoie un booléen, une zone de liste déroulante sépare les options de la sélection, et un bouton radio stocke son élément choisi. Un appel uniforme et unique « donnez-moi la valeur » n'existe pas.
Cet article explique comment extraire les valeurs des champs de formulaire d'un PDF à l'aide de Spire.PDF for JavaScript. La bibliothèque s'exécute sur WebAssembly dans le navigateur, de sorte que le document est analysé localement via un système de fichiers virtuel, sans aller-retour vers le serveur. Vous verrez comment parcourir la collection de champs, effectuer une répartition selon le type de chaque champ, et lire la propriété correcte pour les zones de texte, les zones de liste, les zones de liste déroulante, les boutons radio et les cases à cocher.
Pour l'installation et la configuration du projet, reportez-vous à Intégrer Spire.PDF for JavaScript dans un projet React. Le code ci-dessous suppose que Spire.PDF est installé et que le module WASM est initialisé.
Types de champs en un coup d'œil
Avant de plonger dans l'implémentation, il est utile de cartographier la manière dont chaque type de champ expose sa valeur. Spire.PDF for JavaScript représente les champs de formulaire sous forme de classes de widgets, et la propriété qui contient la valeur actuelle diffère d'un type à l'autre :
| Type de champ | Classe de widget | Propriété à lire | Remarques |
|---|---|---|---|
| Zone de texte | PdfTextBoxFieldWidget |
Text |
Renvoie directement la chaîne saisie. |
| Zone de liste | PdfListBoxWidgetFieldWidget |
SelectedValue |
Values est la liste complète des options, et non le choix de l'utilisateur. |
| Zone de liste déroulante | PdfComboBoxWidgetFieldWidget |
SelectedValue |
Même modèle à double propriété que la zone de liste. |
| Bouton radio | PdfRadioButtonListFieldWidget |
Value |
Fournit la chaîne de l'élément sélectionné en une seule étape. |
| Case à cocher | PdfCheckBoxWidgetFieldWidget |
Checked |
État booléen. Value est indéfini — ne l'utilisez pas. |
Le schéma est clair : il n'existe pas de propriété universelle unique. La logique d'extraction doit tester le type de chaque champ et lire la propriété correspondante, ce que la section suivante met précisément en œuvre.
Parcourir les champs et lire selon le type
Le flux de travail principal comporte trois étapes : charger le PDF, obtenir son formulaire sous forme de PdfFormWidget, puis parcourir la collection FieldsWidget et effectuer un branchement sur la classe de chaque champ à l'aide de instanceof. À chaque branche, lisez la propriété spécifique au type et ajoutez le résultat à une chaîne de rapport. Comme la répartition couvre tous les types pris en charge, vous n'avez pas besoin de connaître à l'avance les champs que contient le document — les champs non reconnus passent simplement à une étiquette par défaut.
function App() {
const getAllFieldValues = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check that the module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load the PDF file to be read into the VFS
const inputFileName = 'ApplicationForm.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);
// Build a PdfFormWidget from the document's form handle; FieldsWidget is its field collection
const formWidget = new pdfModule.PdfFormWidget(doc.Form.H);
const fields = formWidget.FieldsWidget;
let report = '';
// Walk the field collection, check each type, and read the matching value
for (let i = 0; i < fields.Count; i++) {
const field = fields.get_Item({ index: i });
// Both the type name and the value are filled in by the type dispatch
let type = 'Unknown';
let value = '(Unrecognized field type)';
if (field instanceof pdfModule.PdfTextBoxFieldWidget) {
// Text box field: read Text directly
type = 'TextBox';
value = field.Text;
} else if (field instanceof pdfModule.PdfListBoxWidgetFieldWidget) {
// List box field: Values holds every option, SelectedValue is the current one
const options = [];
for (let j = 0; j < field.Values.Count; j++) {
options.push(field.Values.get_Item(j).Value);
}
type = 'ListBox';
value = `Selected ${field.SelectedValue}, options ${options.join(', ')}`;
} else if (field instanceof pdfModule.PdfComboBoxWidgetFieldWidget) {
// Combo box field: like a list box, it has an option collection and a selected value
const options = [];
for (let j = 0; j < field.Values.Count; j++) {
options.push(field.Values.get_Item(j).Value);
}
type = 'ComboBox';
value = `Selected ${field.SelectedValue}, options ${options.join(', ')}`;
} else if (field instanceof pdfModule.PdfRadioButtonListFieldWidget) {
// Radio button field: Value is the selected item
type = 'RadioButton';
value = `Selected ${field.Value}`;
} else if (field instanceof pdfModule.PdfCheckBoxWidgetFieldWidget) {
// Check box field: Checked gives the state, not Value
type = 'CheckBox';
value = field.Checked ? 'Checked' : 'Not checked';
}
report += `Field "${field.Name}" (${type}): ${value}\n`;
}
const outputFileName = 'AllFieldValues.txt';
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>Extract Form Field Values</h1>
<button onClick={getAllFieldValues}>
Extract values
</button>
</div>
);
}
export default App;
Une fois la boucle terminée, la chaîne de rapport contient une ligne par champ avec son nom, son type et sa valeur actuelle. Le fichier est écrit dans le système de fichiers virtuel, puis téléchargé sous forme de fichier texte :

La chaîne instanceof est au cœur de l'approche. Chaque branche sait exactement quelle propriété lire, de sorte que la sortie est correcte quel que soit le nombre de types de champs que le document mélange. Les trois sections suivantes abordent les pièges qui surviennent lorsque la propriété de valeur d'un champ n'est pas celle que vous pourriez attendre.
Cases à cocher : Checked vs Value
Une erreur courante lors de la lecture des champs de case à cocher consiste à se tourner vers une propriété Value. Le widget de case à cocher — PdfCheckBoxWidgetFieldWidget — n'expose pas du tout Value ; toute tentative de lecture renvoie undefined. En interne, une case à cocher suit son état au moyen de valeurs d'exportation : Off lorsqu'elle n'est pas cochée, et Yes ou une chaîne d'exportation personnalisée lorsqu'elle est cochée. Une chaîne brute ne peut pas vous indiquer de manière fiable si la case est sélectionnée, c'est pourquoi la surface de l'API omet délibérément Value et propose Checked à la place.
La solution est simple — utilisez toujours la propriété booléenne Checked :
// Check the state with Checked, not Value
const checked = field.Checked;
Cela renvoie true lorsque la case est cochée et false sinon, vous offrant un booléen propre pour la logique en aval, sans aucune analyse de chaîne.
Zones de liste et zones de liste déroulante : SelectedValue vs Values
Les zones de liste et les zones de liste déroulante partagent un modèle de données en deux parties qui déroute de nombreux développeurs. PdfListBoxWidgetFieldWidget et PdfComboBoxWidgetFieldWidget exposent tous deux une collection Values et une chaîne SelectedValue, et il est facile de supposer que Values contient la saisie de l'utilisateur. Ce n'est pas le cas.
Values est l'ensemble complet des options disponibles. Chaque élément de la collection est un objet PdfListWidgetItem, vous devez donc le déballer avec .Value pour obtenir le texte de l'option. Parcourir Values vous indique ce que l'utilisateur aurait pu choisir, et non ce qu'il a réellement sélectionné. La véritable sélection de l'utilisateur réside dans SelectedValue sous forme de chaîne simple.
Utilisez SelectedValue pour la valeur actuelle, et parcourez Values uniquement lorsque vous devez énumérer les choix disponibles :
// The text of the currently selected item
const selected = field.SelectedValue;
// Every available option
const options = [];
for (let j = 0; j < field.Values.Count; j++) {
options.push(field.Values.get_Item(j).Value);
}
Il est essentiel de bien distinguer ces deux propriétés : traiter Values comme la réponse vous donne la liste des options au lieu du résultat rempli, et les deux ont rarement la même longueur.
Gestion des PDF chiffrés
L'extraction du formulaire commence par l'ouverture du document. Si le PDF est protégé par mot de passe, appeler LoadFromFile avec seulement le nom du fichier génère une erreur — « Impossible d'ouvrir un document chiffré. Le mot de passe n'est pas valide. » — et aucun objet de document n'est renvoyé. Les champs de formulaire ne sont jamais atteints.
La solution consiste à passer le mot de passe d'ouverture en tant que second argument :
doc.LoadFromFile(inputFileName, 'spire123');
Une fois le document ouvert avec succès, le reste du flux d'extraction — construction du PdfFormWidget, parcours des champs, répartition par type — fonctionne exactement de la même manière qu'avec un fichier non chiffré. Le mot de passe ne conditionne que le chargement initial ; il ne modifie pas la manière dont les valeurs des champs sont lues.
Voir aussi
- Intégrer Spire.PDF for JavaScript dans un projet React — installation, configuration et initialisation de WASM
- Remplir les champs de formulaire PDF avec Spire.PDF for JavaScript — écrire des valeurs dans les champs de formulaire par programmation
- Importer et exporter des données de formulaire PDF avec Spire.PDF for JavaScript — sérialiser les données de formulaire dans des fichiers FDF/XFDF
Si vous souhaitez supprimer le message d'évaluation du document résultant, ou vous débarrasser des limitations de fonctionnalités, contactez le service commercial pour une licence temporaire valable 30 jours.