我在iText7上收到com.itextpdf.kernel.PdfException: Document was closed. It is impossible to execute action.错误。

1   // UPDATE FROM HERE
2   PdfFont font;
3   {
4       GcsFilename gcsFilename = new GcsFilename("fonts", "msgothic001.ttf");
5       try (GcsInputChannel inputChannel =
6           gcsService.openPrefetchingReadChannel(gcsFilename, 0, BUFFER_SIZE)) {
7           font =
8               PdfFontFactory.createFont(
9                   getBytes(Channels.newInputStream(inputChannel)),
10                  PdfEncodings.IDENTITY_H,
11                  true);
12      }
13  }
14  // UPDATE UNTIL HERE
15
16  WriterProperties wp = new WriterProperties();
17  wp.useSmartMode();
18  try (PdfDocument writeDoc = new PdfDocument(new PdfWriter(outputStream, wp))) {
19
20      List<Integer> keyList = Arrays.asList(Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3));
21      for (Integer keyNumber : keyList) {
22          LOGGER.info(keyNumber);                                                   // (1)
23          ByteArrayOutputStream baos = new ByteArrayOutputStream();
24          try (PdfWriter writer = new PdfWriter(baos);
25              PdfDocument readDoc =
26                  new PdfDocument(new PdfReader(new ByteArrayInputStream(inputBytes)), writer)) {
27              PdfAcroForm pdfAcroForm = PdfAcroForm.getAcroForm(readDoc, false);
28              Map<String, PdfFormField> fieldMap = pdfAcroForm.getFormFields();
29              if (fieldMap != null && fieldMap.size() > 0) {
30                  Set<String> fieldNameSet = new HashSet<>(fieldMap.keySet());
31                  for (String fieldName : fieldNameSet) {
32                      pdfAcroForm.renameField(fieldName, fieldName + "_" + keyNumber);
33                  }
34                  fieldMap = pdfAcroForm.getFormFields();
35              }
36
37
38              // UPDATE FROM HERE
39              PdfFormField form = fieldMap.get("Customer_" + keyNumber);
40              form.setFont(font).setValue("Test Test");
41              // UPDATE UNTIL HERE
42
43          }                                           // (2) We got the error on this line
44
45          try (PdfDocument readDoc =
46              new PdfDocument(new PdfReader(new ByteArrayInputStream(baos.toByteArray())))) {
47              readDoc.copyPagesTo(1, readDoc.getNumberOfPages(), writeDoc, new PdfPageFormCopier());
48          }
49      }
50  }

我得到了这个输出。
13:55:45.962 1      // (1)
13:55:47.252 2      // (1)
13:55:47.782 com.itextpdf.kernel.PdfException: Document was closed. It is impossible to execute action.
    at com.itextpdf.kernel.pdf.PdfDocument.checkClosingStatus(PdfDocument.java:1887)
    at com.itextpdf.kernel.pdf.PdfDocument.getWriter(PdfDocument.java:645)
    at com.itextpdf.kernel.pdf.PdfObject.makeIndirect(PdfObject.java:228)
    at com.itextpdf.kernel.pdf.PdfDictionary.makeIndirect(PdfDictionary.java:491)
    at com.itextpdf.kernel.pdf.PdfDictionary.makeIndirect(PdfDictionary.java:57)
    at com.itextpdf.kernel.pdf.PdfObject.makeIndirect(PdfObject.java:249)
    at com.itextpdf.kernel.pdf.PdfDictionary.makeIndirect(PdfDictionary.java:479)
    at com.itextpdf.kernel.pdf.PdfDictionary.makeIndirect(PdfDictionary.java:57)
    at com.itextpdf.kernel.font.PdfFont.makeObjectIndirect(PdfFont.java:600)
    at com.itextpdf.kernel.font.PdfType0Font.getFontDescriptor(PdfType0Font.java:672)
    at com.itextpdf.kernel.font.PdfType0Font.flushFontData(PdfType0Font.java:828)
    at com.itextpdf.kernel.font.PdfType0Font.flush(PdfType0Font.java:600)
    at com.itextpdf.kernel.pdf.PdfDocument.flushFonts(PdfDocument.java:1848)
    at com.itextpdf.kernel.pdf.PdfDocument.close(PdfDocument.java:800)
    at (our source (2) )

为什么会出现此错误?我该如何解决?

[更新]
我发现字体“MS Gothic”(日语Windows上的标准字体)的设置值导致此错误。似乎有些字体导致此错误,而另一些则不是。我也尝试过HELVETICA,但它不会导致错误。我已经更新了程序(从1行到14行,以及38行到41行)。

最佳答案

我已经为您的代码制作了几乎文字的副本:

package com.itextpdf.samples;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.itextpdf.forms.PdfAcroForm;
import com.itextpdf.forms.PdfPageFormCopier;
import com.itextpdf.forms.fields.PdfFormField;
import com.itextpdf.io.font.FontProgram;
import com.itextpdf.io.font.FontProgramFactory;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.WriterProperties;

public class Test {

    public static void main(String[] args) throws IOException {
        FontProgram fontProgram = FontProgramFactory.createFont("c:/windows/fonts/msgothic.ttc,1");

        FileOutputStream outputStream = new FileOutputStream("test.pdf");
        WriterProperties wp = new WriterProperties();
        wp.useSmartMode();
        try (PdfDocument writeDoc = new PdfDocument(new PdfWriter(outputStream, wp))) {

            for (int keyNumber = 0; keyNumber < 3; keyNumber++) {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                try (PdfWriter writer = new PdfWriter(baos);
                    PdfDocument readDoc =
                        new PdfDocument(new PdfReader("form.pdf"), writer)) {
                    PdfAcroForm pdfAcroForm = PdfAcroForm.getAcroForm(readDoc, false);
                    Map<String, PdfFormField> fieldMap = pdfAcroForm.getFormFields();
                    if (fieldMap != null && fieldMap.size() > 0) {
                        Set<String> fieldNameSet = new HashSet<>(fieldMap.keySet());
                        for (String fieldName : fieldNameSet) {
                            pdfAcroForm.renameField(fieldName, fieldName + "_" + keyNumber);
                        }
                        fieldMap = pdfAcroForm.getFormFields();
                    }

                    PdfFormField form = fieldMap.get("name_" + keyNumber);
                    form.setFont(PdfFontFactory.createFont(fontProgram)).setValue("Test Test");
                }


                try (PdfDocument readDoc =
                    new PdfDocument(new PdfReader(new ByteArrayInputStream(baos.toByteArray())))) {
                    readDoc.copyPagesTo(1, readDoc.getNumberOfPages(), writeDoc, new PdfPageFormCopier());
                }
            }
        }
    }
}

运行它时不会抛出任何错误。

我必须进行一些更改,因为我不知道keyList等参数是关于什么的。您能否执行我的示例,并告诉我问题是否仍然存在?
  • 如果我的示例仍然抛出错误:也许您未使用iText 7的最新版本。请升级并重新尝试。
  • 如果我的示例没有引发错误:尝试逐步调整我的示例,直到错误再次发生。告诉我们错误发生之前您执行的最后一步。

  • 更新:

    当您创建PdfFont并在PdfFont的上下文中使用该PdfDocument实例时,该PdfFont“属于”该文档,您将无法再使用它。您应该为每个文档创建一个新的PdfFont实例。这并不意味着您不能重用FontProgram

    我将更新我的示例。我使用FontProgramFactory创建一个FontProgram(我使用了快速又脏的方法)。我不重用任何PdfFont,但是我使用FontProgram为每个PdfFont创建一个新的PdfDocument

    10-08 20:00