iText로 가변 페이지 PDF를 생성하려고 할 때 예외 (Exception when attempting to generate variable-page PDF with iText)


문제 설명

iText로 가변 페이지 PDF를 생성하려고 할 때 예외 (Exception when attempting to generate variable‑page PDF with iText)

I'm trying to create an auto‑filled PDF of a government payroll form, which involves the possibility of a variable number of pages. I'm currently storing each page as a Map, with the keys being the names of the fields and the values being their contents. At the moment, I have this code:

in = new FileInputStream(inputPDF);
PdfCopyFields adder = new PdfCopyFields(outStream);
PdfReader reader = null;
PdfStamper stamper = null;
ByteArrayOutputStream baos = null;
for (int pageNum = 0; pageNum < numPages; pageNum++) {
    reader = new PdfReader(in);
    baos = new ByteArrayOutputStream();
    stamper = new PdfStamper(reader, baos);
    AcroFields form = stamper.getAcroFields();
    Map<String, String> page = pages.get(pageNum);
    setFieldsToPage(form, pageNum);
    populatePage(form, page, pageNum);
    stamper.close();
    reader = new PdfReader(baos.toByteArray());
    adder.addDocument(reader);
}

The methods called are:

private void populatePage(AcroFields form, Map<String, String> pageMap, int pageNum) throws Exception {
    ArrayList<String> fieldNames = new ArrayList<String>();
    for (String key : pageMap.keySet()) {
        fieldNames.add(key);
    }
    for (String key : fieldNames) {
        form.setField(key + pageNum, pageMap.get(key));
    }
}

and

private void setFieldsToPage(AcroFields form, int pageNum) {
    ArrayList<String> fieldNames = new ArrayList<String>();
    Map<String, AcroFields.Item> fields = form.getFields();
    for (String fieldName : fields.keySet()) {
        fieldNames.add(fieldName);
    }
    for (String fieldName : fieldNames) {
        form.renameField(fieldName, fieldName + pageNum);
    }
}

The issue is that this throws an exception on the second iteration through the loop: at reader = new PdfReader(in); I get the following exception:  java.io.IOException: PDF header signature not found. What am I doing wrong here, and how do I fix it?

EDIT: Here is the exception:

java.io.IOException: PDF header signature not found.
  at com.lowagie.text.pdf.PRTokeniser.checkPdfHeader(Unknown Source)
  at com.lowagie.text.pdf.PdfReader.readPdf(Unknown Source)
  at com.lowagie.text.pdf.PdfReader.<init>(Unknown Source)
  at com.lowagie.text.pdf.PdfReader.<init>(Unknown Source)

By the way, I'm sorry if the formatting is bad ‑ this is my first time using stackoverflow.


참조 솔루션

방법 1:

Your issue is that you essentially try to read the same input stream multiple times while it is positioned at its end already after the first time:

in = new FileInputStream(inputPDF);
[...]
for (int pageNum = 0; pageNum < numPages; pageNum++) {
    reader = new PdfReader(in);
    [...]
}

The whole stream is read in the first iteration; thus, in the second one new PdfReader(in) essentially tries to parse an empty file resulting in your

  

java.io.IOException: PDF header signature not found

You can fix that by simply constructing the PdfReader with the input file path directly every time:

for (int pageNum = 0; pageNum < numPages; pageNum++) {
    reader = new PdfReader(inputPDF);
    [...]
}

Two more things, though:

  • You don't close your PdfReader instances after use. In the most recent iText versions implicit closing of readers has been taken out of the code as it collides with numerous use cases. Thus, after you finished working with a reader (this includes that any stamper etc using that reader also is closed), you should close the reader explicitly.

  • In general, if you have a PDF already in your file system, opening a PdfReader for it via a FileInputStream is very wasteful resource‑wise ‑‑‑ a reader initialized with an input stream first completely reads that stream into memory (byte[]) and then parses the in‑memory representation; a reader initialized with a file path directly parses on‑disc representation.

방법 2:

The exception tells you that the file you're reading doesn't start with %PDF‑.

Write a small example that doesn't involve iText and check the first 5 bytes of the InputStream in and you'll find out what you're doing wrong (we can't tell you unless you show us those 5 bytes).

(by dais314mklBruno Lowagie)

참조 문서

  1. Exception when attempting to generate variable‑page PDF with iText (CC BY‑SA 3.0/4.0)

#itext #pdf-generation #pdf #java






관련 질문

iText로 가변 페이지 PDF를 생성하려고 할 때 예외 (Exception when attempting to generate variable-page PDF with iText)

Icepdf 특수 문자 렌더링 문제 (Icepdf special character rendering issue)

JAVA에서 PDF 양식 테이블 채우기 (Filling PDF form tables in JAVA)

itext를 사용하여 poi에서 차트 내보내기 (Exporting charts from poi using itext)

표 셀에 사각형을 그리는 방법은 무엇입니까? (How to draw rectangles in a Table cell?)

동적 컨트롤로 PDF 양식 템플릿 수정 (Modify PDF Form Template with dynamic controls)

itext와 같은 라이브러리로 Java 응용 프로그램을 배포하는 방법은 무엇입니까? (how to distribute a java-application with libraries such as itext?)

종이 Itext7에서 첫 번째 줄과 마지막 줄 속성을 제거합니다. (Remove the first and last lines properties in the paper Itext7)

Java에서 iText 5를 사용하여 여러 셀을 만들고 각 셀에 각 문자를 설정하는 방법 (How to create multiple cells and set each character into each cell using iText 5 in Java)

iTextSharp(또는 iText 5)를 사용하여 다른 PdfImportedPage의 배경으로 전체 PdfImportedPage를 추가하는 방법 (How to add a full PdfImportedPage as background for another PdfImportedPage with iTextSharp (or iText 5))

그래픽 텍스트 효과가 있는 텍스트 요소 (Text element with graphical text effects)

iText7을 사용하여 PDFButtonFormField에 이미지를 추가할 때 종횡비를 유지하는 방법 (How to Maintain Aspect Ratio when Adding an Image to a PDFButtonFormField using iText7)







코멘트